@lmnr-ai/lmnr 0.8.50 → 0.8.52

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.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_rolldown_runtime = require("./rolldown-runtime-Ctb5zv51.cjs");
3
- const require_utils = require("./utils-CNR1tzh5.cjs");
3
+ const require_utils = require("./utils-vnm5E0kk.cjs");
4
4
  const require_consts = require("./consts-9rSS0oeR.cjs");
5
5
  let path = require("path");
6
6
  path = require_rolldown_runtime.__toESM(path);
@@ -10,12 +10,9 @@ let _opentelemetry_instrumentation = require("@opentelemetry/instrumentation");
10
10
  let _opentelemetry_sdk_trace_base = require("@opentelemetry/sdk-trace-base");
11
11
  let _opentelemetry_sdk_trace_node = require("@opentelemetry/sdk-trace-node");
12
12
  let _opentelemetry_semantic_conventions = require("@opentelemetry/semantic-conventions");
13
- let _traceloop_instrumentation_anthropic = require("@traceloop/instrumentation-anthropic");
14
13
  let _traceloop_instrumentation_bedrock = require("@traceloop/instrumentation-bedrock");
15
14
  let _traceloop_instrumentation_chromadb = require("@traceloop/instrumentation-chromadb");
16
- let _traceloop_instrumentation_cohere = require("@traceloop/instrumentation-cohere");
17
15
  let _traceloop_instrumentation_langchain = require("@traceloop/instrumentation-langchain");
18
- let _traceloop_instrumentation_openai = require("@traceloop/instrumentation-openai");
19
16
  let _traceloop_instrumentation_pinecone = require("@traceloop/instrumentation-pinecone");
20
17
  let _traceloop_instrumentation_qdrant = require("@traceloop/instrumentation-qdrant");
21
18
  let _traceloop_instrumentation_together = require("@traceloop/instrumentation-together");
@@ -68,6 +65,10 @@ var EvaluationDataset = class {
68
65
  for (let i = Math.max(start, 0); i < Math.min(end, await this.size()); i++) result.push(await this.get(i));
69
66
  return result;
70
67
  }
68
+ async *[Symbol.asyncIterator]() {
69
+ const size = await this.size();
70
+ for (let i = 0; i < size; i++) yield await this.get(i);
71
+ }
71
72
  sourceDataset() {}
72
73
  take(n) {
73
74
  return new Transformed(this, async (base) => {
@@ -144,14 +145,14 @@ var LaminarDataset = class extends EvaluationDataset {
144
145
  fetchPage(offset) {
145
146
  const existing = this.pages.get(offset);
146
147
  if (existing) return existing;
147
- const pending = this.doFetchPage(offset).catch((err) => {
148
+ const pending = this.pullPage(offset).catch((err) => {
148
149
  this.pages.delete(offset);
149
150
  throw err;
150
151
  });
151
152
  this.pages.set(offset, pending);
152
153
  return pending;
153
154
  }
154
- async doFetchPage(offset) {
155
+ async pullPage(offset) {
155
156
  if (!this.client) throw new Error("Client not set");
156
157
  const identifier = this.id ? { id: this.id } : { name: this.name };
157
158
  const resp = await this.client.datasets.pull({
@@ -175,6 +176,17 @@ var LaminarDataset = class extends EvaluationDataset {
175
176
  if (local >= page.length) throw new Error(`Index ${index} is out of range for dataset of size ${this.len ?? "unknown"}`);
176
177
  return page[local];
177
178
  }
179
+ async *[Symbol.asyncIterator]() {
180
+ let offset = 0;
181
+ let yielded = 0;
182
+ while (this.len === null || yielded < this.len) {
183
+ const page = await (this.pages.get(offset) ?? this.pullPage(offset));
184
+ if (page.length === 0) return;
185
+ yield* page;
186
+ yielded += page.length;
187
+ offset += this.fetchSize;
188
+ }
189
+ }
178
190
  /**
179
191
  * Push data from files to this dataset.
180
192
  *
@@ -183,7 +195,7 @@ var LaminarDataset = class extends EvaluationDataset {
183
195
  */
184
196
  async push(paths, recursive = false) {
185
197
  if (!this.client) throw new Error("Client not set");
186
- const { loadFromPaths } = await Promise.resolve().then(() => require("./file-utils-RXJzJyiI.cjs")).then((n) => n.file_utils_exports);
198
+ const { loadFromPaths } = await Promise.resolve().then(() => require("./file-utils-C_q3Dsf2.cjs")).then((n) => n.file_utils_exports);
187
199
  const data = await loadFromPaths(Array.isArray(paths) ? paths : [paths], recursive);
188
200
  if (data.length === 0) {
189
201
  console.warn("No data to push. Skipping");
@@ -199,7 +211,7 @@ var LaminarDataset = class extends EvaluationDataset {
199
211
  };
200
212
  //#endregion
201
213
  //#region src/opentelemetry-lib/tracing/compat.ts
202
- const logger$26 = require_utils.initializeLogger();
214
+ const logger$30 = require_utils.initializeLogger();
203
215
  const makeSpanOtelV2Compatible = (span) => {
204
216
  const spanAny = span;
205
217
  if (spanAny.instrumentationScope && !spanAny.instrumentationLibrary) Object.assign(span, { instrumentationLibrary: spanAny.instrumentationScope });
@@ -245,7 +257,7 @@ const createResource = (attributes) => {
245
257
  if (resources.Resource) return new resources.Resource(attributes);
246
258
  throw new Error("Unable to create Resource: neither v1 nor v2 API found");
247
259
  } catch {
248
- logger$26.debug("Laminar failed to @opentelemetry/resources, continuing without it");
260
+ logger$30.debug("Laminar failed to @opentelemetry/resources, continuing without it");
249
261
  return;
250
262
  }
251
263
  };
@@ -447,7 +459,7 @@ const consumeResponse = async (response) => {
447
459
  };
448
460
  //#endregion
449
461
  //#region src/opentelemetry-lib/tracing/stream-utils.ts
450
- const logger$25 = require_utils.initializeLogger();
462
+ const logger$29 = require_utils.initializeLogger();
451
463
  const pendingStreamProcessing = /* @__PURE__ */ new Set();
452
464
  /**
453
465
  * Wait for all pending stream processing to complete with a timeout
@@ -455,7 +467,7 @@ const pendingStreamProcessing = /* @__PURE__ */ new Set();
455
467
  */
456
468
  const waitForPendingStreams = async (timeoutMs = 5e3) => {
457
469
  if (pendingStreamProcessing.size === 0) return;
458
- logger$25.debug(`Waiting for ${pendingStreamProcessing.size} pending stream(s)`);
470
+ logger$29.debug(`Waiting for ${pendingStreamProcessing.size} pending stream(s)`);
459
471
  const initialCount = pendingStreamProcessing.size;
460
472
  const pendingPromises = Array.from(pendingStreamProcessing);
461
473
  let timedOut = false;
@@ -466,7 +478,7 @@ const waitForPendingStreams = async (timeoutMs = 5e3) => {
466
478
  }, timeoutMs);
467
479
  });
468
480
  await Promise.race([Promise.allSettled(pendingPromises), timeoutPromise]);
469
- if (timedOut && pendingStreamProcessing.size > 0) logger$25.warn(`Timeout waiting for ${pendingStreamProcessing.size} pending stream(s) after ${timeoutMs}ms (started with ${initialCount})`);
481
+ if (timedOut && pendingStreamProcessing.size > 0) logger$29.warn(`Timeout waiting for ${pendingStreamProcessing.size} pending stream(s) after ${timeoutMs}ms (started with ${initialCount})`);
470
482
  };
471
483
  /**
472
484
  * Track a background promise and ensure cleanup
@@ -482,34 +494,34 @@ const trackStreamProcessing = (task) => {
482
494
  * while passing through the original result to the caller
483
495
  */
484
496
  const handleStreamResult = (originalResult, streamInfo, span, ignoreOutput, serialize) => {
485
- logger$25.debug(`Handling stream result of type: ${streamInfo.type}`);
497
+ logger$29.debug(`Handling stream result of type: ${streamInfo.type}`);
486
498
  if (streamInfo.type === "aisdk-result") {
487
499
  trackStreamProcessing(async () => {
488
- logger$25.debug("Starting background processing for AI SDK result");
500
+ logger$29.debug("Starting background processing for AI SDK result");
489
501
  let partialOutput = {};
490
502
  try {
491
503
  partialOutput = await consumeAISDKResult(streamInfo.result);
492
504
  if (shouldSendTraces() && !ignoreOutput) try {
493
505
  span.setAttribute(require_utils.SPAN_OUTPUT, serialize(partialOutput));
494
506
  } catch (error) {
495
- logger$25.warn("Failed to serialize AI SDK stream output: " + require_utils.errorMessage(error));
507
+ logger$29.warn("Failed to serialize AI SDK stream output: " + require_utils.errorMessage(error));
496
508
  }
497
509
  } catch (error) {
498
510
  if (Object.keys(partialOutput).length > 0 && shouldSendTraces() && !ignoreOutput) try {
499
511
  span.setAttribute(require_utils.SPAN_OUTPUT, serialize(partialOutput));
500
512
  } catch (serError) {
501
- logger$25.warn("Failed to serialize partial AI SDK output: " + require_utils.errorMessage(serError));
513
+ logger$29.warn("Failed to serialize partial AI SDK output: " + require_utils.errorMessage(serError));
502
514
  }
503
515
  span.recordException(error);
504
516
  } finally {
505
- logger$25.debug("Ending span for AI SDK result");
517
+ logger$29.debug("Ending span for AI SDK result");
506
518
  span.end();
507
519
  }
508
520
  });
509
521
  return originalResult;
510
522
  }
511
523
  if (streamInfo.type === "readable-stream") {
512
- logger$25.debug("Setting up background processing for ReadableStream");
524
+ logger$29.debug("Setting up background processing for ReadableStream");
513
525
  const { stream, dataPromise } = consumeAndTeeReadableStream(streamInfo.stream);
514
526
  trackStreamProcessing(async () => {
515
527
  try {
@@ -521,18 +533,18 @@ const handleStreamResult = (originalResult, streamInfo, span, ignoreOutput, seri
521
533
  };
522
534
  span.setAttribute(require_utils.SPAN_OUTPUT, serialize(output));
523
535
  } catch (serError) {
524
- logger$25.warn("Failed to serialize stream output: " + require_utils.errorMessage(serError));
536
+ logger$29.warn("Failed to serialize stream output: " + require_utils.errorMessage(serError));
525
537
  }
526
538
  if (error) span.recordException(error);
527
539
  } finally {
528
- logger$25.debug("Ending span for ReadableStream");
540
+ logger$29.debug("Ending span for ReadableStream");
529
541
  span.end();
530
542
  }
531
543
  });
532
544
  return stream;
533
545
  }
534
546
  if (streamInfo.type === "async-iterable") {
535
- logger$25.debug("Setting up background processing for AsyncIterable");
547
+ logger$29.debug("Setting up background processing for AsyncIterable");
536
548
  const { iterable, dataPromise } = consumeAndTeeAsyncIterable(streamInfo.iterable);
537
549
  trackStreamProcessing(async () => {
538
550
  try {
@@ -544,18 +556,18 @@ const handleStreamResult = (originalResult, streamInfo, span, ignoreOutput, seri
544
556
  };
545
557
  span.setAttribute(require_utils.SPAN_OUTPUT, serialize(output));
546
558
  } catch (serError) {
547
- logger$25.warn("Failed to serialize async iterable output: " + require_utils.errorMessage(serError));
559
+ logger$29.warn("Failed to serialize async iterable output: " + require_utils.errorMessage(serError));
548
560
  }
549
561
  if (error) span.recordException(error);
550
562
  } finally {
551
- logger$25.debug("Ending span for AsyncIterable");
563
+ logger$29.debug("Ending span for AsyncIterable");
552
564
  span.end();
553
565
  }
554
566
  });
555
567
  return iterable;
556
568
  }
557
569
  if (streamInfo.type === "response") {
558
- logger$25.debug("Setting up background processing for Response");
570
+ logger$29.debug("Setting up background processing for Response");
559
571
  const originalResponse = streamInfo.response;
560
572
  if (!originalResponse.body) {
561
573
  span.end();
@@ -578,19 +590,19 @@ const handleStreamResult = (originalResult, streamInfo, span, ignoreOutput, seri
578
590
  };
579
591
  span.setAttribute(require_utils.SPAN_OUTPUT, serialize(output));
580
592
  } catch (serError) {
581
- logger$25.warn("Failed to serialize response output: " + require_utils.errorMessage(serError));
593
+ logger$29.warn("Failed to serialize response output: " + require_utils.errorMessage(serError));
582
594
  }
583
595
  if (error) span.recordException(error);
584
596
  } catch (err) {
585
597
  span.recordException(err);
586
598
  } finally {
587
- logger$25.debug("Ending span for Response");
599
+ logger$29.debug("Ending span for Response");
588
600
  span.end();
589
601
  }
590
602
  });
591
603
  return newResponse;
592
604
  }
593
- logger$25.warn("Stream type not handled, ending span immediately");
605
+ logger$29.warn("Stream type not handled, ending span immediately");
594
606
  span.end();
595
607
  return originalResult;
596
608
  };
@@ -668,7 +680,7 @@ const writeDebugSessionFile = (file, dir = process.cwd()) => {
668
680
  * contract. This file is part of the cross-language parity surface — keep its
669
681
  * logic line-comparable with the Python `config.py`.
670
682
  */
671
- const logger$24 = require_utils.initializeLogger();
683
+ const logger$28 = require_utils.initializeLogger();
672
684
  const TRUTHY = /* @__PURE__ */ new Set([
673
685
  "true",
674
686
  "1",
@@ -704,7 +716,7 @@ const parseCacheUntil = (value) => {
704
716
  if (value === void 0 || value === "") return null;
705
717
  const spanId = normalizeSpanId(value);
706
718
  if (spanId !== null) return spanId;
707
- logger$24.warn(`LMNR_DEBUG_CACHE_UNTIL=${JSON.stringify(value)} is not a span id; ignoring`);
719
+ logger$28.warn(`LMNR_DEBUG_CACHE_UNTIL=${JSON.stringify(value)} is not a span id; ignoring`);
708
720
  return null;
709
721
  };
710
722
  /**
@@ -1058,7 +1070,7 @@ const resetDebugRuntime = () => {
1058
1070
  };
1059
1071
  //#endregion
1060
1072
  //#region src/opentelemetry-lib/tracing/span.ts
1061
- const logger$23 = require_utils.initializeLogger();
1073
+ const logger$27 = require_utils.initializeLogger();
1062
1074
  /**
1063
1075
  * Build the debug block to propagate, or undefined when debug mode is off.
1064
1076
  *
@@ -1208,7 +1220,7 @@ var LaminarSpan = class LaminarSpan {
1208
1220
  } catch {}
1209
1221
  metadata[key.replace(`${require_utils.ASSOCIATION_PROPERTIES}.metadata.`, "")] = value;
1210
1222
  }
1211
- } else logger$23.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.");
1223
+ } 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.");
1212
1224
  return {
1213
1225
  spanId: require_utils.otelSpanIdToUUID(this._span.spanContext().spanId),
1214
1226
  traceId: require_utils.otelTraceIdToUUID(this._span.spanContext().traceId),
@@ -1235,14 +1247,14 @@ var LaminarSpan = class LaminarSpan {
1235
1247
  }
1236
1248
  get tags() {
1237
1249
  if (!this._span.attributes) {
1238
- logger$23.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.");
1250
+ 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.");
1239
1251
  return [];
1240
1252
  }
1241
1253
  return this._span.attributes[`lmnr.association.properties.tags`] ?? [];
1242
1254
  }
1243
1255
  get laminarAssociationProperties() {
1244
1256
  if (!this._span.attributes) {
1245
- logger$23.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.");
1257
+ 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.");
1246
1258
  return {};
1247
1259
  }
1248
1260
  try {
@@ -1438,7 +1450,7 @@ var LaminarContextManager = class {
1438
1450
  };
1439
1451
  //#endregion
1440
1452
  //#region src/opentelemetry-lib/instrumentation/claude-agent-sdk/proxy.ts
1441
- const logger$22 = require_utils.initializeLogger();
1453
+ const logger$26 = require_utils.initializeLogger();
1442
1454
  const DEFAULT_ANTHROPIC_BASE_URL = "https://api.anthropic.com";
1443
1455
  const DEFAULT_CC_PROXY_PORT = 45667;
1444
1456
  const CC_PROXY_PORT_ATTEMPTS = 50;
@@ -1692,7 +1704,7 @@ const resolveTargetUrlFromEnv = (envDict, fallback = DEFAULT_ANTHROPIC_BASE_URL,
1692
1704
  if (foundryBaseUrl) return foundryBaseUrl.replace(/\/$/, "");
1693
1705
  const foundryResource = getEnvValue(FOUNDRY_RESOURCE_ENV);
1694
1706
  if (foundryResource) return `https://${foundryResource}.services.ai.azure.com/anthropic`;
1695
- logger$22.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.`);
1707
+ 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.`);
1696
1708
  return null;
1697
1709
  }
1698
1710
  if (isTruthyEnv(getEnvValue(BEDROCK_USE_ENV))) {
@@ -1704,7 +1716,7 @@ const resolveTargetUrlFromEnv = (envDict, fallback = DEFAULT_ANTHROPIC_BASE_URL,
1704
1716
  region = getRegionFromAwsConfig(awsProfile) ?? void 0;
1705
1717
  }
1706
1718
  if (region) return `https://bedrock-runtime.${region}.amazonaws.com`;
1707
- logger$22.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.`);
1719
+ 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.`);
1708
1720
  return null;
1709
1721
  }
1710
1722
  if (isTruthyEnv(getEnvValue(VERTEX_USE_ENV))) {
@@ -1787,11 +1799,11 @@ const waitForPort = (port, timeoutMs = 5e3) => new Promise((resolve) => {
1787
1799
  const registerGlobalProxyShutdown = () => {
1788
1800
  if (!globalShutdownRegistered) {
1789
1801
  process.on("exit", () => {
1790
- logger$22.debug("process.on(\"exit\") called - stopping all active proxies");
1802
+ logger$26.debug("process.on(\"exit\") called - stopping all active proxies");
1791
1803
  for (const proxyServer of activeProxyServers) try {
1792
1804
  proxyServer.stopServer();
1793
1805
  } catch (e) {
1794
- logger$22.debug(`Failed to stop proxy: ${require_utils.errorMessage(e)}`);
1806
+ logger$26.debug(`Failed to stop proxy: ${require_utils.errorMessage(e)}`);
1795
1807
  }
1796
1808
  activeProxyServers.clear();
1797
1809
  });
@@ -1806,28 +1818,28 @@ const createProxyInstance = async ({ env, cwd, settingSources, settings, targetU
1806
1818
  try {
1807
1819
  const port = await findAvailablePort(DEFAULT_CC_PROXY_PORT, CC_PROXY_PORT_ATTEMPTS);
1808
1820
  if (port === null) {
1809
- logger$22.warn("Unable to allocate port for cc-proxy.");
1821
+ logger$26.warn("Unable to allocate port for cc-proxy.");
1810
1822
  return null;
1811
1823
  }
1812
1824
  const targetUrl = resolvedTargetUrl ?? resolveTargetUrlFromEnv(env, void 0, cwd, settingSources, settings);
1813
1825
  if (!targetUrl) {
1814
- logger$22.warn("Unable to resolve target URL for cc-proxy (provider misconfigured).");
1826
+ logger$26.warn("Unable to resolve target URL for cc-proxy (provider misconfigured).");
1815
1827
  return null;
1816
1828
  }
1817
- logger$22.debug(`Creating proxy instance on port ${port} targeting: ${targetUrl}`);
1829
+ logger$26.debug(`Creating proxy instance on port ${port} targeting: ${targetUrl}`);
1818
1830
  try {
1819
1831
  const { ProxyServer } = require("@lmnr-ai/claude-code-proxy");
1820
1832
  const proxyServer = new ProxyServer(port);
1821
1833
  proxyServer.runServer(targetUrl);
1822
1834
  if (!await waitForPort(port)) {
1823
- logger$22.warn(`cc-proxy failed to start on port ${port}`);
1835
+ logger$26.warn(`cc-proxy failed to start on port ${port}`);
1824
1836
  proxyServer.stopServer();
1825
1837
  return null;
1826
1838
  }
1827
1839
  const proxyBaseUrl = `http://127.0.0.1:${port}`;
1828
1840
  activeProxyServers.add(proxyServer);
1829
1841
  registerGlobalProxyShutdown();
1830
- logger$22.info(`Started claude proxy server on: ${proxyBaseUrl}`);
1842
+ logger$26.info(`Started claude proxy server on: ${proxyBaseUrl}`);
1831
1843
  return {
1832
1844
  server: proxyServer,
1833
1845
  baseUrl: proxyBaseUrl,
@@ -1835,11 +1847,11 @@ const createProxyInstance = async ({ env, cwd, settingSources, settings, targetU
1835
1847
  targetUrl
1836
1848
  };
1837
1849
  } catch (e) {
1838
- logger$22.warn(`Unable to start cc-proxy: ${require_utils.errorMessage(e)}`);
1850
+ logger$26.warn(`Unable to start cc-proxy: ${require_utils.errorMessage(e)}`);
1839
1851
  return null;
1840
1852
  }
1841
1853
  } catch (e) {
1842
- logger$22.warn(`Failed to create proxy instance: ${require_utils.errorMessage(e)}`);
1854
+ logger$26.warn(`Failed to create proxy instance: ${require_utils.errorMessage(e)}`);
1843
1855
  return null;
1844
1856
  }
1845
1857
  };
@@ -1849,11 +1861,11 @@ const createProxyInstance = async ({ env, cwd, settingSources, settings, targetU
1849
1861
  const stopProxyInstance = (instance) => {
1850
1862
  if (!instance) return;
1851
1863
  try {
1852
- logger$22.debug(`Stopping proxy instance on port ${instance.port}`);
1864
+ logger$26.debug(`Stopping proxy instance on port ${instance.port}`);
1853
1865
  instance.server.stopServer();
1854
1866
  activeProxyServers.delete(instance.server);
1855
1867
  } catch (e) {
1856
- logger$22.debug(`Failed to stop proxy instance: ${require_utils.errorMessage(e)}`);
1868
+ logger$26.debug(`Failed to stop proxy instance: ${require_utils.errorMessage(e)}`);
1857
1869
  }
1858
1870
  };
1859
1871
  /**
@@ -1861,11 +1873,11 @@ const stopProxyInstance = (instance) => {
1861
1873
  * Used during shutdown to ensure cleanup
1862
1874
  */
1863
1875
  const forceReleaseProxy = () => {
1864
- logger$22.debug(`Force stopping all ${activeProxyServers.size} active proxy servers`);
1876
+ logger$26.debug(`Force stopping all ${activeProxyServers.size} active proxy servers`);
1865
1877
  for (const proxyServer of activeProxyServers) try {
1866
1878
  proxyServer.stopServer();
1867
1879
  } catch (e) {
1868
- logger$22.debug(`Failed to stop proxy: ${require_utils.errorMessage(e)}`);
1880
+ logger$26.debug(`Failed to stop proxy: ${require_utils.errorMessage(e)}`);
1869
1881
  }
1870
1882
  activeProxyServers.clear();
1871
1883
  };
@@ -1915,14 +1927,14 @@ const setTraceToProxyInstance = async (instance) => {
1915
1927
  spanPath: payload.span_path,
1916
1928
  laminarUrl: payload.laminar_url
1917
1929
  });
1918
- logger$22.debug(`Set trace context to proxy on port ${instance.port}`);
1930
+ logger$26.debug(`Set trace context to proxy on port ${instance.port}`);
1919
1931
  } catch (e) {
1920
- logger$22.debug(`Unable to set trace context to proxy on port ${instance.port}: ` + require_utils.errorMessage(e));
1932
+ logger$26.debug(`Unable to set trace context to proxy on port ${instance.port}: ` + require_utils.errorMessage(e));
1921
1933
  }
1922
1934
  };
1923
1935
  //#endregion
1924
1936
  //#region src/opentelemetry-lib/instrumentation/claude-agent-sdk/index.ts
1925
- const logger$21 = require_utils.initializeLogger();
1937
+ const logger$25 = require_utils.initializeLogger();
1926
1938
  /**
1927
1939
  * Create an instrumented version of the claude-agent-sdk query function.
1928
1940
  * This can be used when importing the query function before Laminar initialization.
@@ -1958,9 +1970,9 @@ function instrumentClaudeAgentQuery(originalQuery) {
1958
1970
  targetUrl
1959
1971
  });
1960
1972
  if (proxyInstance && targetUrl) {
1961
- logger$21.debug(`Using proxy on port ${proxyInstance.port}`);
1973
+ logger$25.debug(`Using proxy on port ${proxyInstance.port}`);
1962
1974
  await Laminar.withSpan(span, async () => {
1963
- logger$21.debug("Setting trace to proxy instance...");
1975
+ logger$25.debug("Setting trace to proxy instance...");
1964
1976
  await setTraceToProxyInstance(proxyInstance);
1965
1977
  });
1966
1978
  const varsToRemove = getEnvVarsToRemove(mergedEnv, sessionCwd, settingSources);
@@ -1975,13 +1987,13 @@ function instrumentClaudeAgentQuery(originalQuery) {
1975
1987
  if (isProviderEnabledInEnv(subprocessEnv, "CLAUDE_CODE_USE_BEDROCK")) subprocessEnv.ANTHROPIC_BEDROCK_BASE_URL = proxyInstance.baseUrl;
1976
1988
  if (isProviderEnabledInEnv(subprocessEnv, "CLAUDE_CODE_USE_VERTEX")) subprocessEnv.ANTHROPIC_VERTEX_BASE_URL = proxyInstance.baseUrl;
1977
1989
  const flagSettings = buildProxyFlagSettings(callerSettings, proxyInstance.baseUrl, sessionCwd, settingSources);
1978
- if (flagSettings === null) logger$21.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.`);
1990
+ 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.`);
1979
1991
  else {
1980
1992
  params.options.settings = flagSettings;
1981
1993
  const conflicting = Object.entries(readClaudeSettingsEnv(sessionCwd, settingSources)).filter(([key, value]) => PROXY_BASE_URL_ENV_KEYS.includes(key) && value !== "" && value !== proxyInstance?.baseUrl).map(([key]) => key);
1982
- if (conflicting.length > 0) logger$21.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.`);
1994
+ 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.`);
1983
1995
  }
1984
- } else logger$21.debug("No claude proxy server available. Proceeding without proxy.");
1996
+ } else logger$25.debug("No claude proxy server available. Proceeding without proxy.");
1985
1997
  const originalGenerator = originalQuery(params);
1986
1998
  for await (const message of originalGenerator) {
1987
1999
  collected.push(message);
@@ -2010,7 +2022,7 @@ var ClaudeAgentSDKInstrumentation = class extends _opentelemetry_instrumentation
2010
2022
  }
2011
2023
  manuallyInstrument(claudeAgentModule) {
2012
2024
  if (claudeAgentModule.query && typeof claudeAgentModule.query === "function") this._wrap(claudeAgentModule, "query", this.patchQuery());
2013
- else logger$21.debug("query function not found in claudeAgentSDK module, skipping instrumentation");
2025
+ else logger$25.debug("query function not found in claudeAgentSDK module, skipping instrumentation");
2014
2026
  }
2015
2027
  patchQuery() {
2016
2028
  return (original) => instrumentClaudeAgentQuery(original);
@@ -2028,7 +2040,7 @@ var ClaudeAgentSDKInstrumentation = class extends _opentelemetry_instrumentation
2028
2040
  //#endregion
2029
2041
  //#region src/laminar.ts
2030
2042
  require_utils.loadEnv();
2031
- const logger$20 = require_utils.initializeLogger();
2043
+ const logger$24 = require_utils.initializeLogger();
2032
2044
  var Laminar = class Laminar {
2033
2045
  static {
2034
2046
  this.isInitialized = false;
@@ -2121,7 +2133,7 @@ var Laminar = class Laminar {
2121
2133
  */
2122
2134
  static initialize({ projectApiKey, baseUrl, baseHttpUrl, httpPort, grpcPort, instrumentModules, disableBatch, traceExportTimeoutMillis, logLevel, maxExportBatchSize, maxExportBatchSizeBytes, flushBySize, forceHttp, sessionRecordingOptions, metadata, inheritGlobalContext, spanProcessor } = {}) {
2123
2135
  if (this.isInitialized) {
2124
- logger$20.warn("Laminar has already been initialized. Skipping initialization.");
2136
+ logger$24.warn("Laminar has already been initialized. Skipping initialization.");
2125
2137
  return;
2126
2138
  }
2127
2139
  const key = projectApiKey ?? process?.env?.LMNR_PROJECT_API_KEY;
@@ -2145,7 +2157,7 @@ var Laminar = class Laminar {
2145
2157
  ...metadata ?? {}
2146
2158
  };
2147
2159
  if (inheritGlobalContext) LaminarContextManager.inheritGlobalContext = true;
2148
- if (spanProcessor && !(spanProcessor instanceof LaminarSpanProcessor)) logger$20.warn("Span processor is not a LaminarSpanProcessor. Some functionality may be impaired.");
2160
+ if (spanProcessor && !(spanProcessor instanceof LaminarSpanProcessor)) logger$24.warn("Span processor is not a LaminarSpanProcessor. Some functionality may be impaired.");
2149
2161
  this.isInitialized = true;
2150
2162
  const urlWithoutSlash = url?.replace(/\/$/, "").replace(/:\d{1,5}$/g, "");
2151
2163
  const httpUrlWithoutSlash = httpUrl?.replace(/\/$/, "").replace(/:\d{1,5}$/g, "");
@@ -2192,11 +2204,11 @@ var Laminar = class Laminar {
2192
2204
  try {
2193
2205
  getRuntime()?.recordTraceId(require_utils.otelTraceIdToUUID(otelSpanContext.traceId));
2194
2206
  } catch (e) {
2195
- logger$20.debug("Failed to record debug trace id from env: " + require_utils.errorMessage(e));
2207
+ logger$24.debug("Failed to record debug trace id from env: " + require_utils.errorMessage(e));
2196
2208
  }
2197
- logger$20.debug("Initialized Laminar parent context from LMNR_SPAN_CONTEXT.");
2209
+ logger$24.debug("Initialized Laminar parent context from LMNR_SPAN_CONTEXT.");
2198
2210
  } catch (e) {
2199
- logger$20.warn("LMNR_SPAN_CONTEXT is set but could not be used: " + require_utils.errorMessage(e));
2211
+ logger$24.warn("LMNR_SPAN_CONTEXT is set but could not be used: " + require_utils.errorMessage(e));
2200
2212
  }
2201
2213
  }
2202
2214
  /**
@@ -2240,7 +2252,7 @@ var Laminar = class Laminar {
2240
2252
  if (projectId) {
2241
2253
  runtime.recordProjectId(projectId);
2242
2254
  const sessionUrl = runtime.debuggerSessionUrl();
2243
- logger$20.info(`Laminar debugger session: ${sessionUrl}`);
2255
+ logger$24.info(`Laminar debugger session: ${sessionUrl}`);
2244
2256
  if (runtime.shouldOpenBrowser) {
2245
2257
  const opener = process.platform === "win32" ? "start" : process.platform === "darwin" ? "open" : "xdg-open";
2246
2258
  (0, node_child_process.spawn)(opener, [sessionUrl], {
@@ -2250,7 +2262,7 @@ var Laminar = class Laminar {
2250
2262
  }
2251
2263
  }
2252
2264
  }).catch((e) => {
2253
- logger$20.warn("Failed to register debug session: " + require_utils.errorMessage(e));
2265
+ logger$24.warn("Failed to register debug session: " + require_utils.errorMessage(e));
2254
2266
  });
2255
2267
  this.globalMetadata = {
2256
2268
  ...this.globalMetadata,
@@ -2260,7 +2272,7 @@ var Laminar = class Laminar {
2260
2272
  this.debugExitHook = () => runtime.emitPointer();
2261
2273
  process.once("exit", this.debugExitHook);
2262
2274
  } catch (e) {
2263
- logger$20.warn("Failed to initialize debug runtime: " + require_utils.errorMessage(e));
2275
+ logger$24.warn("Failed to initialize debug runtime: " + require_utils.errorMessage(e));
2264
2276
  }
2265
2277
  }
2266
2278
  /**
@@ -2307,7 +2319,7 @@ var Laminar = class Laminar {
2307
2319
  runtime.rolloutSessions.register({ sessionId: runtime.sessionId }).then((projectId) => {
2308
2320
  if (projectId) runtime.recordProjectId(projectId);
2309
2321
  }).catch((e) => {
2310
- logger$20.debug("Failed to register downstream debug session: " + require_utils.errorMessage(e));
2322
+ logger$24.debug("Failed to register downstream debug session: " + require_utils.errorMessage(e));
2311
2323
  });
2312
2324
  this.globalMetadata = {
2313
2325
  ...this.globalMetadata,
@@ -2316,7 +2328,7 @@ var Laminar = class Laminar {
2316
2328
  LaminarContextManager.setGlobalMetadata(this.globalMetadata);
2317
2329
  }
2318
2330
  } catch (e) {
2319
- logger$20.debug("Failed to arm debug runtime from context: " + require_utils.errorMessage(e));
2331
+ logger$24.debug("Failed to arm debug runtime from context: " + require_utils.errorMessage(e));
2320
2332
  }
2321
2333
  }
2322
2334
  /**
@@ -2331,7 +2343,7 @@ var Laminar = class Laminar {
2331
2343
  */
2332
2344
  static patch(modules) {
2333
2345
  if (!this.isInitialized) {
2334
- logger$20.warn("Laminar must be initialized before patching modules. Skipping patch.");
2346
+ logger$24.warn("Laminar must be initialized before patching modules. Skipping patch.");
2335
2347
  return;
2336
2348
  }
2337
2349
  if (!modules || Object.keys(modules).length === 0) throw new Error("Pass at least one module to patch");
@@ -2591,7 +2603,7 @@ var Laminar = class Laminar {
2591
2603
  const spanContext = require_utils.tryToOtelSpanContext(laminarContext);
2592
2604
  entityContext = _opentelemetry_api.trace.setSpan(entityContext, _opentelemetry_api.trace.wrapSpanContext(spanContext));
2593
2605
  } catch (e) {
2594
- logger$20.warn("Failed to parse parent span context: " + require_utils.errorMessage(e));
2606
+ logger$24.warn("Failed to parse parent span context: " + require_utils.errorMessage(e));
2595
2607
  }
2596
2608
  const tagProperties = tags ? { [`${require_utils.ASSOCIATION_PROPERTIES}.tags`]: Array.from(new Set(tags)) } : {};
2597
2609
  const ctxAssociationProperties = LaminarContextManager.getAssociationProperties();
@@ -2695,13 +2707,13 @@ var Laminar = class Laminar {
2695
2707
  }
2696
2708
  static async flush() {
2697
2709
  if (this.isInitialized) {
2698
- logger$20.debug("Flushing spans");
2710
+ logger$24.debug("Flushing spans");
2699
2711
  await forceFlush();
2700
2712
  }
2701
2713
  }
2702
2714
  static async shutdown() {
2703
2715
  if (this.isInitialized) {
2704
- logger$20.debug("Shutting down Laminar");
2716
+ logger$24.debug("Shutting down Laminar");
2705
2717
  getRuntime()?.emitPointer();
2706
2718
  await forceFlush();
2707
2719
  this.isInitialized = false;
@@ -2836,7 +2848,7 @@ return module.exports;
2836
2848
  //#endregion
2837
2849
  //#region src/browser/utils.ts
2838
2850
  const LMNR_SEND_EVENTS_FUNCTION_NAME = "lmnrSendEvents";
2839
- const logger$19 = require_utils.initializeLogger();
2851
+ const logger$23 = require_utils.initializeLogger();
2840
2852
  /**
2841
2853
  * If the first argument is a string, return an object with the name of the method
2842
2854
  * and the argument as the value.
@@ -2859,7 +2871,7 @@ const takeFullSnapshot = async (page) => await page.evaluate(() => {
2859
2871
  window.lmnrRrweb.record.takeFullSnapshot();
2860
2872
  return true;
2861
2873
  } catch (error) {
2862
- logger$19.error("Error taking full snapshot: " + require_utils.errorMessage(error));
2874
+ logger$23.error("Error taking full snapshot: " + require_utils.errorMessage(error));
2863
2875
  return false;
2864
2876
  }
2865
2877
  return false;
@@ -2870,7 +2882,7 @@ const injectSessionRecorder = async (page, sessionRecordingOptions) => {
2870
2882
  try {
2871
2883
  return await script();
2872
2884
  } catch (error) {
2873
- logger$19.error("Operation " + script.name + " failed: " + require_utils.errorMessage(error));
2885
+ logger$23.error("Operation " + script.name + " failed: " + require_utils.errorMessage(error));
2874
2886
  }
2875
2887
  await new Promise((resolve) => setTimeout(resolve, 500));
2876
2888
  }
@@ -2880,20 +2892,20 @@ const injectSessionRecorder = async (page, sessionRecordingOptions) => {
2880
2892
  try {
2881
2893
  isRrwebPresent = await castedPage.evaluate(() => typeof window.lmnrRrweb !== "undefined");
2882
2894
  } catch (error) {
2883
- logger$19.debug("Failed to check if session recorder is loaded: " + require_utils.errorMessage(error));
2895
+ logger$23.debug("Failed to check if session recorder is loaded: " + require_utils.errorMessage(error));
2884
2896
  }
2885
2897
  if (!isRrwebPresent) {
2886
2898
  if (!await tryRunScript(async function injectSessionRecorder() {
2887
2899
  await castedPage.evaluate(RECORDER);
2888
2900
  return true;
2889
2901
  })) {
2890
- logger$19.error("Failed to load session recorder");
2902
+ logger$23.error("Failed to load session recorder");
2891
2903
  return;
2892
2904
  }
2893
2905
  try {
2894
2906
  await castedPage.evaluate(injectScript, sessionRecordingOptions);
2895
2907
  } catch (error) {
2896
- logger$19.debug("Failed to inject session recorder: " + require_utils.errorMessage(error));
2908
+ logger$23.debug("Failed to inject session recorder: " + require_utils.errorMessage(error));
2897
2909
  }
2898
2910
  }
2899
2911
  };
@@ -3159,7 +3171,7 @@ async function sendEvents(chunk, client, chunkBuffers, sessionId, traceId) {
3159
3171
  try {
3160
3172
  const { batchId, chunkIndex, totalChunks, data } = chunk;
3161
3173
  if (!sessionId || !traceId) {
3162
- logger$19.debug("Missing sessionId or traceId in chunk");
3174
+ logger$23.debug("Missing sessionId or traceId in chunk");
3163
3175
  return;
3164
3176
  }
3165
3177
  if (!chunkBuffers.has(batchId)) chunkBuffers.set(batchId, {
@@ -3178,7 +3190,7 @@ async function sendEvents(chunk, client, chunkBuffers, sessionId, traceId) {
3178
3190
  traceId,
3179
3191
  events
3180
3192
  }).catch((error) => {
3181
- logger$19.debug("Failed to send events: " + require_utils.errorMessage(error));
3193
+ logger$23.debug("Failed to send events: " + require_utils.errorMessage(error));
3182
3194
  });
3183
3195
  chunkBuffers.delete(batchId);
3184
3196
  }
@@ -3186,16 +3198,16 @@ async function sendEvents(chunk, client, chunkBuffers, sessionId, traceId) {
3186
3198
  const toDelete = [];
3187
3199
  for (const [bid, buffer] of chunkBuffers.entries()) if (currentTime - buffer.timestamp > OLD_BUFFER_TIMEOUT) toDelete.push(bid);
3188
3200
  for (const bid of toDelete) {
3189
- logger$19.debug(`Cleaning up incomplete chunk buffer: ${bid}`);
3201
+ logger$23.debug(`Cleaning up incomplete chunk buffer: ${bid}`);
3190
3202
  chunkBuffers.delete(bid);
3191
3203
  }
3192
3204
  } catch (error) {
3193
- logger$19.debug("Could not send events: " + require_utils.errorMessage(error));
3205
+ logger$23.debug("Could not send events: " + require_utils.errorMessage(error));
3194
3206
  }
3195
3207
  }
3196
3208
  //#endregion
3197
3209
  //#region src/browser/playwright.ts
3198
- const logger$18 = require_utils.initializeLogger();
3210
+ const logger$22 = require_utils.initializeLogger();
3199
3211
  var PlaywrightInstrumentation = class extends _opentelemetry_instrumentation.InstrumentationBase {
3200
3212
  constructor(client, sessionRecordingOptions) {
3201
3213
  super("@lmnr/playwright-instrumentation", require_utils.version, { enabled: true });
@@ -3303,7 +3315,7 @@ var PlaywrightInstrumentation = class extends _opentelemetry_instrumentation.Ins
3303
3315
  try {
3304
3316
  await injectSessionRecorder(page, this._sessionRecordingOptions);
3305
3317
  } catch (error) {
3306
- logger$18.error("Error in onLoad handler: " + require_utils.errorMessage(error));
3318
+ logger$22.error("Error in onLoad handler: " + require_utils.errorMessage(error));
3307
3319
  }
3308
3320
  });
3309
3321
  const chunkBuffers = /* @__PURE__ */ new Map();
@@ -3313,7 +3325,7 @@ var PlaywrightInstrumentation = class extends _opentelemetry_instrumentation.Ins
3313
3325
  await sendEvents(chunk, this._client, chunkBuffers, sessionId, traceId);
3314
3326
  });
3315
3327
  } catch (error) {
3316
- logger$18.debug("Could not expose function lmnrSendEvents: " + require_utils.errorMessage(error));
3328
+ logger$22.debug("Could not expose function lmnrSendEvents: " + require_utils.errorMessage(error));
3317
3329
  }
3318
3330
  }
3319
3331
  };
@@ -3738,7 +3750,7 @@ var StagehandV2Instrumentation = class extends _opentelemetry_instrumentation.In
3738
3750
  };
3739
3751
  //#endregion
3740
3752
  //#region src/browser/puppeteer.ts
3741
- const logger$17 = require_utils.initializeLogger();
3753
+ const logger$21 = require_utils.initializeLogger();
3742
3754
  var PuppeteerInstrumentation = class extends _opentelemetry_instrumentation.InstrumentationBase {
3743
3755
  constructor(client, sessionRecordingOptions) {
3744
3756
  super("@lmnr/puppeteer-instrumentation", require_utils.version, { enabled: true });
@@ -3783,10 +3795,10 @@ var PuppeteerInstrumentation = class extends _opentelemetry_instrumentation.Inst
3783
3795
  context.on("targetcreated", (target) => {
3784
3796
  target.page().then((page) => {
3785
3797
  if (page) plugin.patchPage(page, sessionId).catch((error) => {
3786
- logger$17.error("Failed to patch page: " + require_utils.errorMessage(error));
3798
+ logger$21.error("Failed to patch page: " + require_utils.errorMessage(error));
3787
3799
  });
3788
3800
  }).catch((error) => {
3789
- logger$17.error("Failed to patch page: " + require_utils.errorMessage(error));
3801
+ logger$21.error("Failed to patch page: " + require_utils.errorMessage(error));
3790
3802
  });
3791
3803
  });
3792
3804
  await Promise.all((await context.pages()).map((page) => plugin.patchPage(page, sessionId)));
@@ -3804,19 +3816,19 @@ var PuppeteerInstrumentation = class extends _opentelemetry_instrumentation.Inst
3804
3816
  context.on("targetcreated", (target) => {
3805
3817
  target.page().then((page) => {
3806
3818
  if (page) plugin.patchPage(page, sessionId).catch((error) => {
3807
- logger$17.error("Failed to patch page: " + require_utils.errorMessage(error));
3819
+ logger$21.error("Failed to patch page: " + require_utils.errorMessage(error));
3808
3820
  });
3809
3821
  }).catch((error) => {
3810
- logger$17.error("Failed to patch page: " + require_utils.errorMessage(error));
3822
+ logger$21.error("Failed to patch page: " + require_utils.errorMessage(error));
3811
3823
  });
3812
3824
  });
3813
3825
  context.on("targetchanged", (target) => {
3814
3826
  target.page().then((page) => {
3815
3827
  if (page) plugin.patchPage(page, sessionId).catch((error) => {
3816
- logger$17.error("Failed to patch page: " + require_utils.errorMessage(error));
3828
+ logger$21.error("Failed to patch page: " + require_utils.errorMessage(error));
3817
3829
  });
3818
3830
  }).catch((error) => {
3819
- logger$17.error("Failed to patch page: " + require_utils.errorMessage(error));
3831
+ logger$21.error("Failed to patch page: " + require_utils.errorMessage(error));
3820
3832
  });
3821
3833
  });
3822
3834
  for (const page of await context.pages()) await plugin.patchPage(page, sessionId);
@@ -3840,7 +3852,7 @@ var PuppeteerInstrumentation = class extends _opentelemetry_instrumentation.Inst
3840
3852
  const traceId = otelTraceId ? require_utils.otelTraceIdToUUID(otelTraceId) : require_utils.NIL_UUID;
3841
3853
  page.on("domcontentloaded", () => {
3842
3854
  injectSessionRecorder(page, this._sessionRecordingOptions).catch((error) => {
3843
- logger$17.error("Error in onLoad handler: " + require_utils.errorMessage(error));
3855
+ logger$21.error("Error in onLoad handler: " + require_utils.errorMessage(error));
3844
3856
  });
3845
3857
  });
3846
3858
  await injectSessionRecorder(page, this._sessionRecordingOptions);
@@ -3850,13 +3862,13 @@ var PuppeteerInstrumentation = class extends _opentelemetry_instrumentation.Inst
3850
3862
  await sendEvents(chunk, this._client, chunkBuffers, sessionId, traceId);
3851
3863
  });
3852
3864
  } catch (error) {
3853
- logger$17.debug("Could not expose function lmnrSendEvents: " + require_utils.errorMessage(error));
3865
+ logger$21.debug("Could not expose function lmnrSendEvents: " + require_utils.errorMessage(error));
3854
3866
  }
3855
3867
  }
3856
3868
  };
3857
3869
  //#endregion
3858
3870
  //#region src/browser/stagehand/v3/constants.ts
3859
- const logger$16 = require_utils.initializeLogger();
3871
+ const logger$20 = require_utils.initializeLogger();
3860
3872
  const CDP_OPERATION_TIMEOUT_MS = 1e4;
3861
3873
  const SKIP_URL_PATTERNS = [
3862
3874
  "about:blank",
@@ -3907,7 +3919,7 @@ async function getOrCreateIsolatedWorld(page) {
3907
3919
  frameId
3908
3920
  };
3909
3921
  } catch (error) {
3910
- logger$16.debug("Failed to create isolated world: " + require_utils.errorMessage(error));
3922
+ logger$20.debug("Failed to create isolated world: " + require_utils.errorMessage(error));
3911
3923
  return null;
3912
3924
  }
3913
3925
  }
@@ -3924,7 +3936,7 @@ async function isRecorderPresent(page, contextId) {
3924
3936
  if (!result) return true;
3925
3937
  return result.result?.value === true;
3926
3938
  } catch (error) {
3927
- logger$16.debug("Failed to check if recorder is present: " + require_utils.errorMessage(error));
3939
+ logger$20.debug("Failed to check if recorder is present: " + require_utils.errorMessage(error));
3928
3940
  return true;
3929
3941
  }
3930
3942
  }
@@ -3937,21 +3949,21 @@ async function injectRecorderViaCDP(page, state, conn, sessionRecordingOptions,
3937
3949
  try {
3938
3950
  url = page.url();
3939
3951
  } catch (error) {
3940
- logger$16.debug("Failed to get page URL, page might be closed: " + require_utils.errorMessage(error));
3952
+ logger$20.debug("Failed to get page URL, page might be closed: " + require_utils.errorMessage(error));
3941
3953
  return null;
3942
3954
  }
3943
3955
  if (shouldSkipUrl(url)) {
3944
- logger$16.debug(`Skipping recorder injection for URL: ${url}`);
3956
+ logger$20.debug(`Skipping recorder injection for URL: ${url}`);
3945
3957
  return null;
3946
3958
  }
3947
3959
  const worldResult = await getOrCreateIsolatedWorld(page);
3948
3960
  if (!worldResult) {
3949
- logger$16.debug("Failed to get isolated world for page");
3961
+ logger$20.debug("Failed to get isolated world for page");
3950
3962
  return null;
3951
3963
  }
3952
3964
  const { contextId, frameId } = worldResult;
3953
3965
  if (await isRecorderPresent(page, contextId)) {
3954
- logger$16.debug("Recorder already present, skipping injection");
3966
+ logger$20.debug("Recorder already present, skipping injection");
3955
3967
  state.contextIdToSession.set(contextId, {
3956
3968
  sessionId: state.sessionId,
3957
3969
  traceId: state.traceId
@@ -3964,7 +3976,7 @@ async function injectRecorderViaCDP(page, state, conn, sessionRecordingOptions,
3964
3976
  contextId
3965
3977
  });
3966
3978
  } catch (error) {
3967
- logger$16.debug("Failed to inject rrweb: " + require_utils.errorMessage(error));
3979
+ logger$20.debug("Failed to inject rrweb: " + require_utils.errorMessage(error));
3968
3980
  return null;
3969
3981
  }
3970
3982
  const optionsJson = JSON.stringify(sessionRecordingOptions ?? {});
@@ -3975,14 +3987,14 @@ async function injectRecorderViaCDP(page, state, conn, sessionRecordingOptions,
3975
3987
  contextId
3976
3988
  });
3977
3989
  } catch (error) {
3978
- logger$16.debug("Failed to inject recording setup: " + require_utils.errorMessage(error));
3990
+ logger$20.debug("Failed to inject recording setup: " + require_utils.errorMessage(error));
3979
3991
  return null;
3980
3992
  }
3981
3993
  try {
3982
3994
  await sendCDP(page, "Runtime.addBinding", { name: "lmnrSendEvents" });
3983
- logger$16.debug(`Added binding 'lmnrSendEvents' for page ${frameId}, context ${contextId}`);
3995
+ logger$20.debug(`Added binding 'lmnrSendEvents' for page ${frameId}, context ${contextId}`);
3984
3996
  } catch (error) {
3985
- logger$16.debug("Binding may already exist: " + require_utils.errorMessage(error));
3997
+ logger$20.debug("Binding may already exist: " + require_utils.errorMessage(error));
3986
3998
  }
3987
3999
  if (bindingHandler) try {
3988
4000
  const pageTargetId = page.targetId();
@@ -3992,26 +4004,26 @@ async function injectRecorderViaCDP(page, state, conn, sessionRecordingOptions,
3992
4004
  const sessionTyped = session;
3993
4005
  if (sessionTyped.on) {
3994
4006
  sessionTyped.on("Runtime.bindingCalled", bindingHandler);
3995
- logger$16.debug(`Set up binding handler on session ${sessionId}`);
4007
+ logger$20.debug(`Set up binding handler on session ${sessionId}`);
3996
4008
  }
3997
4009
  } catch (error) {
3998
- logger$16.debug(`Failed to set up binding handler on session ${sessionId}: ` + require_utils.errorMessage(error));
4010
+ logger$20.debug(`Failed to set up binding handler on session ${sessionId}: ` + require_utils.errorMessage(error));
3999
4011
  }
4000
4012
  state.pageSessionHandlers.set(pageTargetId, bindingHandler);
4001
4013
  }
4002
4014
  } catch (error) {
4003
- logger$16.debug("Failed to set up binding handler: " + require_utils.errorMessage(error));
4015
+ logger$20.debug("Failed to set up binding handler: " + require_utils.errorMessage(error));
4004
4016
  }
4005
4017
  state.contextIdToSession.set(contextId, {
4006
4018
  sessionId: state.sessionId,
4007
4019
  traceId: state.traceId
4008
4020
  });
4009
- logger$16.debug(`Registered context mapping: contextId=${contextId}, sessionId=${state.sessionId}`);
4021
+ logger$20.debug(`Registered context mapping: contextId=${contextId}, sessionId=${state.sessionId}`);
4010
4022
  state.instrumentedPageIds.add(frameId);
4011
- logger$16.debug(`Successfully injected recorder into page ${frameId}`);
4023
+ logger$20.debug(`Successfully injected recorder into page ${frameId}`);
4012
4024
  return contextId;
4013
4025
  } catch (error) {
4014
- logger$16.debug("Error injecting recorder: " + require_utils.errorMessage(error));
4026
+ logger$20.debug("Error injecting recorder: " + require_utils.errorMessage(error));
4015
4027
  return null;
4016
4028
  }
4017
4029
  }
@@ -4025,13 +4037,13 @@ function createBindingHandler(state) {
4025
4037
  if (event.name !== "lmnrSendEvents") return;
4026
4038
  const sessionInfo = state.contextIdToSession.get(event.executionContextId);
4027
4039
  if (!sessionInfo) {
4028
- logger$16.debug("No session info found for context ID: " + event.executionContextId);
4040
+ logger$20.debug("No session info found for context ID: " + event.executionContextId);
4029
4041
  if (state.contextIdToSession.size > 0) {
4030
4042
  const [, fallbackInfo] = state.contextIdToSession.entries().next().value;
4031
4043
  if (fallbackInfo) try {
4032
4044
  sendEvents(JSON.parse(event.payload), state.client, state.chunkBuffers, fallbackInfo.sessionId, fallbackInfo.traceId);
4033
4045
  } catch (error) {
4034
- logger$16.debug("Failed to parse binding payload: " + require_utils.errorMessage(error));
4046
+ logger$20.debug("Failed to parse binding payload: " + require_utils.errorMessage(error));
4035
4047
  }
4036
4048
  }
4037
4049
  return;
@@ -4039,7 +4051,7 @@ function createBindingHandler(state) {
4039
4051
  try {
4040
4052
  sendEvents(JSON.parse(event.payload), state.client, state.chunkBuffers, sessionInfo.sessionId, sessionInfo.traceId);
4041
4053
  } catch (error) {
4042
- logger$16.debug("Failed to handle binding event: " + require_utils.errorMessage(error));
4054
+ logger$20.debug("Failed to handle binding event: " + require_utils.errorMessage(error));
4043
4055
  }
4044
4056
  };
4045
4057
  }
@@ -4055,10 +4067,10 @@ function createTargetCreatedHandler(context, state, sessionRecordingOptions) {
4055
4067
  const pageId = page.mainFrameId();
4056
4068
  if (!state.instrumentedPageIds.has(pageId)) await injectRecorderViaCDP(page, state, context.conn, sessionRecordingOptions, state.bindingHandler ?? void 0);
4057
4069
  } catch (error) {
4058
- logger$16.debug("Error injecting recorder into new page: " + require_utils.errorMessage(error));
4070
+ logger$20.debug("Error injecting recorder into new page: " + require_utils.errorMessage(error));
4059
4071
  }
4060
4072
  } catch (error) {
4061
- logger$16.debug("Error handling target created event: " + require_utils.errorMessage(error));
4073
+ logger$20.debug("Error handling target created event: " + require_utils.errorMessage(error));
4062
4074
  }
4063
4075
  };
4064
4076
  }
@@ -4070,7 +4082,7 @@ function createTargetInfoChangedHandler(context, state, sessionRecordingOptions)
4070
4082
  if (event.targetInfo.type !== "page") return;
4071
4083
  const url = event.targetInfo.url;
4072
4084
  if (shouldSkipUrl(url)) return;
4073
- logger$16.debug(`Target URL changed to ${url}, checking if recorder injection needed`);
4085
+ logger$20.debug(`Target URL changed to ${url}, checking if recorder injection needed`);
4074
4086
  await new Promise((resolve) => setTimeout(resolve, 150));
4075
4087
  try {
4076
4088
  for (const page of context.pages()) if (page.targetId() === event.targetInfo.targetId) {
@@ -4078,7 +4090,7 @@ function createTargetInfoChangedHandler(context, state, sessionRecordingOptions)
4078
4090
  break;
4079
4091
  }
4080
4092
  } catch (error) {
4081
- logger$16.debug("Error handling target info change: " + require_utils.errorMessage(error));
4093
+ logger$20.debug("Error handling target info change: " + require_utils.errorMessage(error));
4082
4094
  }
4083
4095
  };
4084
4096
  }
@@ -4239,12 +4251,12 @@ var StagehandInstrumentation = class extends _opentelemetry_instrumentation.Inst
4239
4251
  */
4240
4252
  async setupSessionRecording(stagehandInstance, sessionId, traceId) {
4241
4253
  if (!this._client) {
4242
- logger$16.debug("No Laminar client available, skipping session recording setup");
4254
+ logger$20.debug("No Laminar client available, skipping session recording setup");
4243
4255
  return;
4244
4256
  }
4245
4257
  const context = stagehandInstance.context;
4246
4258
  if (!context || !context.conn) {
4247
- logger$16.debug("No context or connection available, skipping session recording setup");
4259
+ logger$20.debug("No context or connection available, skipping session recording setup");
4248
4260
  return;
4249
4261
  }
4250
4262
  const recorderState = {
@@ -4274,11 +4286,11 @@ var StagehandInstrumentation = class extends _opentelemetry_instrumentation.Inst
4274
4286
  for (const page of pages) try {
4275
4287
  if (await injectRecorderViaCDP(page, recorderState, context.conn, this._sessionRecordingOptions, bindingHandler) !== null) injectedCount++;
4276
4288
  } catch (error) {
4277
- logger$16.debug("Error injecting recorder into page: " + require_utils.errorMessage(error));
4289
+ logger$20.debug("Error injecting recorder into page: " + require_utils.errorMessage(error));
4278
4290
  }
4279
- logger$16.debug(`Injected session recorder into ${injectedCount} of ${pages.length} existing page(s)`);
4291
+ logger$20.debug(`Injected session recorder into ${injectedCount} of ${pages.length} existing page(s)`);
4280
4292
  } catch (error) {
4281
- logger$16.debug("Error accessing pages for recorder injection: " + require_utils.errorMessage(error));
4293
+ logger$20.debug("Error accessing pages for recorder injection: " + require_utils.errorMessage(error));
4282
4294
  }
4283
4295
  }
4284
4296
  patchStagehandClose() {
@@ -4308,12 +4320,12 @@ var StagehandInstrumentation = class extends _opentelemetry_instrumentation.Inst
4308
4320
  if (recorderState.targetCreatedHandler) try {
4309
4321
  context.conn.off("Target.targetCreated", recorderState.targetCreatedHandler);
4310
4322
  } catch (error) {
4311
- logger$16.debug("Error removing target created handler: " + require_utils.errorMessage(error));
4323
+ logger$20.debug("Error removing target created handler: " + require_utils.errorMessage(error));
4312
4324
  }
4313
4325
  if (recorderState.targetInfoChangedHandler) try {
4314
4326
  context.conn.off("Target.targetInfoChanged", recorderState.targetInfoChangedHandler);
4315
4327
  } catch (error) {
4316
- logger$16.debug("Error removing target info changed handler: " + require_utils.errorMessage(error));
4328
+ logger$20.debug("Error removing target info changed handler: " + require_utils.errorMessage(error));
4317
4329
  }
4318
4330
  }
4319
4331
  recorderState.contextIdToSession.clear();
@@ -4324,7 +4336,7 @@ var StagehandInstrumentation = class extends _opentelemetry_instrumentation.Inst
4324
4336
  recorderState.targetCreatedHandler = null;
4325
4337
  recorderState.targetInfoChangedHandler = null;
4326
4338
  this.stagehandInstanceToRecorderState.delete(stagehandInstance);
4327
- logger$16.debug("Cleaned up session recording for Stagehand instance");
4339
+ logger$20.debug("Cleaned up session recording for Stagehand instance");
4328
4340
  }
4329
4341
  patchStagehandGlobalMethod(methodName, sessionId, parentSpan) {
4330
4342
  return (original) => async function method(...args) {
@@ -4672,9 +4684,11 @@ function extractToolDefinitions(config) {
4672
4684
  }
4673
4685
  /**
4674
4686
  * Set request attributes on a span from generateContent params.
4687
+ * Also used by the google-aiplatform (Vertex AI) instrumentation, which
4688
+ * reshapes its requests into the same `{model, contents, config}` form.
4675
4689
  */
4676
- function setRequestAttributes$2(span, params, traceContent) {
4677
- safeSetAttribute$2(span, LLM_SYSTEM, "gemini");
4690
+ function setRequestAttributes$5(span, params, traceContent, system = "gemini") {
4691
+ safeSetAttribute$2(span, LLM_SYSTEM, system);
4678
4692
  safeSetAttribute$2(span, LLM_REQUEST_MODEL, params?.model);
4679
4693
  const config = params?.config;
4680
4694
  if (config) {
@@ -4700,7 +4714,7 @@ function setRequestAttributes$2(span, params, traceContent) {
4700
4714
  /**
4701
4715
  * Set response attributes on a span from a GenerateContentResponse.
4702
4716
  */
4703
- function setResponseAttributes$2(span, response, traceContent) {
4717
+ function setResponseAttributes$5(span, response, traceContent) {
4704
4718
  if (!response) return;
4705
4719
  safeSetAttribute$2(span, LLM_RESPONSE_MODEL, response.modelVersion);
4706
4720
  const usage = response.usageMetadata;
@@ -4802,7 +4816,7 @@ function wrapStreamingResponse(span, asyncGen, traceContent) {
4802
4816
  try {
4803
4817
  if (modelVersion !== void 0 || role !== void 0 || accumulatedParts.length > 0 || sawUsageMetadata) {
4804
4818
  const mergedParts = mergeTextParts(accumulatedParts);
4805
- setResponseAttributes$2(span, {
4819
+ setResponseAttributes$5(span, {
4806
4820
  modelVersion,
4807
4821
  candidates: [{ content: {
4808
4822
  role: role ?? "model",
@@ -4831,177 +4845,1548 @@ function wrapStreamingResponse(span, asyncGen, traceContent) {
4831
4845
  return wrapper();
4832
4846
  }
4833
4847
  //#endregion
4834
- //#region src/opentelemetry-lib/instrumentation/google-genai/index.ts
4835
- const WRAPPED_SYMBOL$1 = Symbol("lmnr.google-genai.wrapped");
4836
- const CLASS_PATCH_DATA_SYMBOL = Symbol("lmnr.google-genai.classPatchData");
4837
- var GoogleGenAiInstrumentation = class extends _opentelemetry_instrumentation.InstrumentationBase {
4848
+ //#region src/opentelemetry-lib/instrumentation/anthropic/utils.ts
4849
+ const ANTHROPIC_SYSTEM = "anthropic";
4850
+ const INPUT_MESSAGES$2 = "gen_ai.input.messages";
4851
+ const OUTPUT_MESSAGES$2 = "gen_ai.output.messages";
4852
+ const createStreamState$1 = () => ({
4853
+ usage: {},
4854
+ blocks: [],
4855
+ completion: ""
4856
+ });
4857
+ const toJson$1 = (value) => {
4858
+ if (value === void 0 || value === null) return void 0;
4859
+ return JSON.stringify(value);
4860
+ };
4861
+ const extractStructuredOutputSchema$1 = (params) => {
4862
+ const outputFormat = params?.output_format;
4863
+ if (outputFormat && typeof outputFormat === "object") return toJson$1(outputFormat.schema ?? outputFormat);
4864
+ const schema = params?.output_config?.format?.schema;
4865
+ if (schema && typeof schema === "object") return toJson$1(schema);
4866
+ };
4867
+ const buildInputMessages$1 = (params) => {
4868
+ if (params?.prompt !== void 0 && params?.prompt !== null) return [{
4869
+ role: "user",
4870
+ content: params.prompt
4871
+ }];
4872
+ if (!Array.isArray(params?.messages)) return void 0;
4873
+ const messages = [];
4874
+ if (params.system) messages.push({
4875
+ role: "system",
4876
+ content: params.system
4877
+ });
4878
+ messages.push(...params.messages);
4879
+ return messages;
4880
+ };
4881
+ const setRequestAttributes$4 = (span, params, traceContent) => {
4882
+ safeSetAttribute$2(span, "gen_ai.system", ANTHROPIC_SYSTEM);
4883
+ safeSetAttribute$2(span, "gen_ai.request.model", params?.model);
4884
+ safeSetAttribute$2(span, "gen_ai.request.max_tokens", params?.max_tokens ?? params?.max_tokens_to_sample);
4885
+ safeSetAttribute$2(span, "gen_ai.request.temperature", params?.temperature);
4886
+ safeSetAttribute$2(span, "gen_ai.request.top_p", params?.top_p);
4887
+ safeSetAttribute$2(span, "gen_ai.request.frequency_penalty", params?.frequency_penalty);
4888
+ safeSetAttribute$2(span, "gen_ai.request.presence_penalty", params?.presence_penalty);
4889
+ safeSetAttribute$2(span, "llm.is_streaming", params?.stream);
4890
+ safeSetAttribute$2(span, "anthropic.request.service_tier", params?.service_tier);
4891
+ if (traceContent) {
4892
+ safeSetAttribute$2(span, INPUT_MESSAGES$2, toJson$1(buildInputMessages$1(params)));
4893
+ safeSetAttribute$2(span, "gen_ai.tool.definitions", toJson$1(params?.tools));
4894
+ }
4895
+ safeSetAttribute$2(span, "gen_ai.request.structured_output_schema", extractStructuredOutputSchema$1(params));
4896
+ };
4897
+ const setUsageAttributes$1 = (span, usage, includeTotal) => {
4898
+ if (!usage || typeof usage !== "object" || !Object.keys(usage).length) return;
4899
+ const promptTokens = usage.input_tokens ?? 0;
4900
+ const cacheReadTokens = usage.cache_read_input_tokens ?? 0;
4901
+ const cacheCreationTokens = usage.cache_creation_input_tokens ?? 0;
4902
+ const outputTokens = usage.output_tokens ?? 0;
4903
+ const inputTokens = promptTokens + cacheReadTokens + cacheCreationTokens;
4904
+ span.setAttribute("gen_ai.usage.input_tokens", inputTokens);
4905
+ span.setAttribute("gen_ai.usage.output_tokens", outputTokens);
4906
+ if (includeTotal) span.setAttribute("llm.usage.total_tokens", inputTokens + outputTokens);
4907
+ span.setAttribute("gen_ai.usage.cache_read_input_tokens", cacheReadTokens);
4908
+ span.setAttribute("gen_ai.usage.cache_creation_input_tokens", cacheCreationTokens);
4909
+ };
4910
+ /**
4911
+ * Response attributes for a non-streaming `Message` (or legacy `Completion`).
4912
+ */
4913
+ const setResponseAttributes$4 = (span, response, traceContent) => {
4914
+ if (!response || typeof response !== "object") return;
4915
+ safeSetAttribute$2(span, "gen_ai.response.model", response.model);
4916
+ safeSetAttribute$2(span, "gen_ai.response.id", response.id);
4917
+ safeSetAttribute$2(span, "anthropic.response.service_tier", response.usage?.service_tier);
4918
+ setUsageAttributes$1(span, response.usage, true);
4919
+ if (traceContent) {
4920
+ const output = {
4921
+ role: response.role ?? "assistant",
4922
+ content: []
4923
+ };
4924
+ if (response.stop_reason) output.stop_reason = response.stop_reason;
4925
+ if (response.completion) output.content.push({
4926
+ type: "text",
4927
+ text: response.completion
4928
+ });
4929
+ else if (Array.isArray(response.content)) output.content.push(...response.content);
4930
+ safeSetAttribute$2(span, OUTPUT_MESSAGES$2, toJson$1([output]));
4931
+ }
4932
+ span.setStatus({ code: _opentelemetry_api.SpanStatusCode.OK });
4933
+ };
4934
+ const mergeUsage = (state, usage) => {
4935
+ if (!usage || typeof usage !== "object") return;
4936
+ for (const [key, value] of Object.entries(usage)) if (value !== null && value !== void 0) state.usage[key] = value;
4937
+ };
4938
+ /**
4939
+ * Fold one raw stream event (`RawMessageStreamEvent`, or a legacy completion
4940
+ * chunk) into the accumulated state.
4941
+ */
4942
+ const processStreamEvent$1 = (state, event) => {
4943
+ switch (event?.type) {
4944
+ case "message_start": {
4945
+ const message = event.message ?? {};
4946
+ state.id = message.id;
4947
+ state.model = message.model;
4948
+ mergeUsage(state, message.usage);
4949
+ state.serviceTier = message.usage?.service_tier ?? void 0;
4950
+ break;
4951
+ }
4952
+ case "content_block_start": {
4953
+ const block = { ...event.content_block };
4954
+ if ("input" in block) block.input = "";
4955
+ state.blocks[event.index] = block;
4956
+ break;
4957
+ }
4958
+ case "content_block_delta": {
4959
+ const block = state.blocks[event.index];
4960
+ const delta = event.delta ?? {};
4961
+ if (!block) break;
4962
+ if (delta.type === "text_delta") block.text = (block.text ?? "") + (delta.text ?? "");
4963
+ else if (delta.type === "thinking_delta") block.thinking = (block.thinking ?? "") + (delta.thinking ?? "");
4964
+ else if (delta.type === "input_json_delta") block.input = (block.input ?? "") + (delta.partial_json ?? "");
4965
+ break;
4966
+ }
4967
+ case "message_delta":
4968
+ if (event.delta?.stop_reason) state.stopReason = event.delta.stop_reason;
4969
+ mergeUsage(state, event.usage);
4970
+ break;
4971
+ case "completion":
4972
+ state.id = event.id ?? state.id;
4973
+ state.model = event.model ?? state.model;
4974
+ state.completion += event.completion ?? "";
4975
+ if (event.stop_reason) state.stopReason = event.stop_reason;
4976
+ }
4977
+ };
4978
+ const parseToolInput = (input) => {
4979
+ if (typeof input !== "string") return input;
4980
+ if (input === "") return {};
4981
+ try {
4982
+ return JSON.parse(input);
4983
+ } catch {
4984
+ return input;
4985
+ }
4986
+ };
4987
+ const buildStreamedContent = (state) => {
4988
+ if (state.completion) return [{
4989
+ type: "text",
4990
+ text: state.completion
4991
+ }];
4992
+ const content = [];
4993
+ for (const block of state.blocks) {
4994
+ if (!block) continue;
4995
+ if (block.type === "text") {
4996
+ if (block.text) content.push({
4997
+ type: "text",
4998
+ text: block.text
4999
+ });
5000
+ } else if (block.type === "thinking") content.push({
5001
+ type: "thinking",
5002
+ thinking: block.thinking ?? ""
5003
+ });
5004
+ else if ("input" in block) content.push({
5005
+ ...block,
5006
+ input: parseToolInput(block.input)
5007
+ });
5008
+ else content.push(block);
5009
+ }
5010
+ return content;
5011
+ };
5012
+ const setStreamingResponseAttributes = (span, state, traceContent) => {
5013
+ safeSetAttribute$2(span, "gen_ai.response.id", state.id);
5014
+ safeSetAttribute$2(span, "gen_ai.response.model", state.model);
5015
+ safeSetAttribute$2(span, "anthropic.response.service_tier", state.usage.service_tier ?? state.serviceTier);
5016
+ setUsageAttributes$1(span, state.usage, false);
5017
+ if (traceContent) {
5018
+ const output = {
5019
+ role: "assistant",
5020
+ content: buildStreamedContent(state)
5021
+ };
5022
+ if (state.stopReason) output.stop_reason = state.stopReason;
5023
+ safeSetAttribute$2(span, OUTPUT_MESSAGES$2, toJson$1([output]));
5024
+ }
5025
+ };
5026
+ //#endregion
5027
+ //#region src/opentelemetry-lib/instrumentation/anthropic/index.ts
5028
+ const logger$19 = require_utils.initializeLogger();
5029
+ const PATCH_DATA_SYMBOL$3 = Symbol("lmnr.anthropic.patchData");
5030
+ const hasOwnPatchData$2 = (proto) => Object.getOwnPropertyDescriptor(proto, PATCH_DATA_SYMBOL$3) !== void 0;
5031
+ const markSpanError$3 = (span, error) => {
5032
+ span.recordException(error);
5033
+ span.setAttribute("error.type", error?.constructor?.name ?? "Error");
5034
+ span.setStatus({ code: _opentelemetry_api.SpanStatusCode.ERROR });
5035
+ };
5036
+ /**
5037
+ * Attribute extraction must never break the user's call.
5038
+ */
5039
+ const safely$3 = (fn) => {
5040
+ try {
5041
+ fn();
5042
+ } catch (error) {
5043
+ logger$19.debug(`Failed to set anthropic span attributes: ${String(error)}`);
5044
+ }
5045
+ };
5046
+ const isAsyncIterable$3 = (value) => value !== null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function";
5047
+ /**
5048
+ * Resolve the `Anthropic` client class from the module namespace, its default
5049
+ * export, or the class itself.
5050
+ */
5051
+ const resolveClientClass$1 = (mod) => {
5052
+ for (const candidate of [
5053
+ mod?.Anthropic,
5054
+ mod?.default,
5055
+ mod
5056
+ ]) if (typeof candidate?.Messages === "function") return candidate;
5057
+ };
5058
+ /**
5059
+ * Instruments `@anthropic-ai/sdk`: `messages.create`, `beta.messages.create`
5060
+ * and the legacy `completions.create`. `messages.parse()` and
5061
+ * `messages.stream()` (and their beta counterparts) delegate to `create`, so
5062
+ * they are traced through it without nesting a second span.
5063
+ */
5064
+ var AnthropicInstrumentation = class extends _opentelemetry_instrumentation.InstrumentationBase {
4838
5065
  constructor(config) {
4839
- super("@lmnr/google-genai-instrumentation", require_utils.version, { enabled: true });
5066
+ super("@lmnr/anthropic-instrumentation", require_utils.version, { enabled: true });
4840
5067
  this.traceContent = config?.traceContent ?? true;
4841
5068
  }
4842
5069
  init() {
4843
- return new _opentelemetry_instrumentation.InstrumentationNodeModuleDefinition("@google/genai", [">=1.0.0"], this.patch.bind(this), this.unpatch.bind(this));
5070
+ return new _opentelemetry_instrumentation.InstrumentationNodeModuleDefinition("@anthropic-ai/sdk", [">=0.9.1"], this.patch.bind(this), this.unpatch.bind(this));
4844
5071
  }
4845
- manuallyInstrument(genaiModule) {
4846
- _opentelemetry_api.diag.debug("Manually instrumenting @google/genai");
4847
- const GoogleGenAIClass = this.resolveGoogleGenAIClass(genaiModule);
4848
- if (GoogleGenAIClass) this.patchGoogleGenAIClass(GoogleGenAIClass);
4849
- else _opentelemetry_api.diag.warn("Could not find GoogleGenAI class in google_genai manual instrumentation input. Pass either GoogleGenAI class or module object with GoogleGenAI export.");
5072
+ /**
5073
+ * Accepts the `@anthropic-ai/sdk` module namespace or the `Anthropic`
5074
+ * class (the module's default export).
5075
+ */
5076
+ manuallyInstrument(module) {
5077
+ if (!resolveClientClass$1(module)) {
5078
+ _opentelemetry_api.diag.warn("Could not find the Anthropic client in anthropic manual instrumentation input. Pass the @anthropic-ai/sdk module.");
5079
+ return;
5080
+ }
5081
+ _opentelemetry_api.diag.debug("Manually instrumenting @anthropic-ai/sdk");
5082
+ this.patch(module);
4850
5083
  }
4851
5084
  patch(moduleExports) {
4852
- _opentelemetry_api.diag.debug("Patching @google/genai");
4853
- const GoogleGenAIClass = this.resolveGoogleGenAIClass(moduleExports);
4854
- if (GoogleGenAIClass) this.patchGoogleGenAIClass(GoogleGenAIClass);
5085
+ _opentelemetry_api.diag.debug("Patching @anthropic-ai/sdk");
5086
+ const [completions, ...messages] = this.resourcePrototypes(moduleExports);
5087
+ this.patchCreate(completions, "anthropic.completion");
5088
+ for (const proto of messages) this.patchCreate(proto, "anthropic.chat");
4855
5089
  return moduleExports;
4856
5090
  }
4857
5091
  unpatch(moduleExports) {
4858
- _opentelemetry_api.diag.debug("Unpatching @google/genai");
4859
- const GoogleGenAIClass = this.resolveGoogleGenAIClass(moduleExports);
4860
- if (GoogleGenAIClass) this.unpatchGoogleGenAIClass(GoogleGenAIClass);
5092
+ _opentelemetry_api.diag.debug("Unpatching @anthropic-ai/sdk");
5093
+ for (const proto of this.resourcePrototypes(moduleExports)) {
5094
+ if (!proto || !hasOwnPatchData$2(proto)) continue;
5095
+ proto.create = proto[PATCH_DATA_SYMBOL$3].original;
5096
+ delete proto[PATCH_DATA_SYMBOL$3];
5097
+ }
4861
5098
  }
4862
- resolveGoogleGenAIClass(moduleOrClass) {
4863
- if (typeof moduleOrClass === "function") return moduleOrClass;
4864
- if (moduleOrClass?.GoogleGenAI && typeof moduleOrClass.GoogleGenAI === "function") return moduleOrClass.GoogleGenAI;
5099
+ /**
5100
+ * `[Completions, Messages, Beta.Messages]` prototypes; entries are
5101
+ * undefined where the installed SDK version lacks the resource.
5102
+ */
5103
+ resourcePrototypes(moduleExports) {
5104
+ const client = resolveClientClass$1(moduleExports);
5105
+ return [
5106
+ client?.Completions?.prototype,
5107
+ client?.Messages?.prototype,
5108
+ client?.Beta?.Messages?.prototype
5109
+ ];
4865
5110
  }
4866
- patchGoogleGenAIClass(GoogleGenAIClass) {
4867
- const classPatchData = GoogleGenAIClass[CLASS_PATCH_DATA_SYMBOL];
4868
- if (classPatchData) {
4869
- classPatchData.instrumentation = this;
4870
- classPatchData.traceContent = this.traceContent;
4871
- return;
4872
- }
4873
- const originalModelsDescriptor = Object.getOwnPropertyDescriptor(GoogleGenAIClass.prototype, "models");
4874
- if (originalModelsDescriptor && !originalModelsDescriptor.configurable) {
4875
- _opentelemetry_api.diag.warn("Could not patch GoogleGenAI.prototype.models: descriptor is non-configurable.");
5111
+ /**
5112
+ * Replace `proto.create` with a traced wrapper. Re-patching an already
5113
+ * patched prototype only refreshes `traceContent`, so repeated
5114
+ * initialization never double-wraps.
5115
+ */
5116
+ patchCreate(proto, spanName) {
5117
+ if (!proto || typeof proto.create !== "function") return;
5118
+ if (hasOwnPatchData$2(proto)) {
5119
+ proto[PATCH_DATA_SYMBOL$3].traceContent = this.traceContent;
4876
5120
  return;
4877
5121
  }
4878
5122
  const patchData = {
4879
- instrumentation: this,
4880
5123
  traceContent: this.traceContent,
4881
- originalModelsDescriptor
5124
+ original: proto.create
4882
5125
  };
4883
- Object.defineProperty(GoogleGenAIClass, CLASS_PATCH_DATA_SYMBOL, {
5126
+ Object.defineProperty(proto, PATCH_DATA_SYMBOL$3, {
4884
5127
  value: patchData,
4885
5128
  writable: true,
4886
5129
  configurable: true,
4887
5130
  enumerable: false
4888
5131
  });
4889
- Object.defineProperty(GoogleGenAIClass.prototype, "models", {
4890
- configurable: true,
4891
- enumerable: originalModelsDescriptor?.enumerable ?? true,
4892
- get: function() {
4893
- if (originalModelsDescriptor?.get) return originalModelsDescriptor.get.call(this);
4894
- },
4895
- set: function(value) {
4896
- patchData.instrumentation.patchModelsInstance(value, patchData);
4897
- if (originalModelsDescriptor?.set) {
4898
- originalModelsDescriptor.set.call(this, value);
4899
- return;
4900
- }
4901
- Object.defineProperty(this, "models", {
4902
- value,
4903
- writable: true,
4904
- configurable: true,
4905
- enumerable: true
4906
- });
4907
- }
4908
- });
5132
+ proto.create = wrapCreate(patchData, spanName);
4909
5133
  }
4910
- unpatchGoogleGenAIClass(GoogleGenAIClass) {
4911
- const classPatchData = GoogleGenAIClass[CLASS_PATCH_DATA_SYMBOL];
4912
- if (!classPatchData) return;
4913
- if (classPatchData.originalModelsDescriptor) Object.defineProperty(GoogleGenAIClass.prototype, "models", classPatchData.originalModelsDescriptor);
4914
- else delete GoogleGenAIClass.prototype.models;
4915
- delete GoogleGenAIClass[CLASS_PATCH_DATA_SYMBOL];
5134
+ };
5135
+ const wrapCreate = (patchData, spanName) => function(params, ...rest) {
5136
+ const { original } = patchData;
5137
+ if ((0, _opentelemetry_core.isTracingSuppressed)(_opentelemetry_api.context.active())) return original.call(this, params, ...rest);
5138
+ const traceContent = patchData.traceContent;
5139
+ const span = Laminar.startSpan({
5140
+ name: spanName,
5141
+ spanType: "LLM"
5142
+ });
5143
+ safely$3(() => setRequestAttributes$4(span, params, traceContent));
5144
+ let result;
5145
+ try {
5146
+ result = Laminar.withSpan(span, () => ({ value: original.call(this, params, ...rest) })).value;
5147
+ } catch (error) {
5148
+ markSpanError$3(span, error);
5149
+ span.end();
5150
+ throw error;
4916
5151
  }
4917
- patchModelsInstance(models, classPatchData) {
4918
- if (!models || typeof models !== "object") return;
4919
- if (typeof models.generateContent !== "function") return;
4920
- if (typeof models.generateContentStream !== "function") return;
4921
- if (models[WRAPPED_SYMBOL$1]) return;
4922
- const originalGenerateContent = models.generateContent.bind(models);
4923
- const originalGenerateContentStream = models.generateContentStream.bind(models);
4924
- models.generateContent = async function(params) {
4925
- if ((0, _opentelemetry_core.isTracingSuppressed)(_opentelemetry_api.context.active())) return originalGenerateContent(params);
4926
- const span = Laminar.startSpan({
4927
- name: "gemini.generate_content",
4928
- spanType: "LLM"
4929
- });
4930
- setRequestAttributes$2(span, params, classPatchData.traceContent);
4931
- return Laminar.withSpan(span, async () => {
4932
- try {
4933
- const response = await originalGenerateContent(params);
4934
- setResponseAttributes$2(span, response, classPatchData.traceContent);
4935
- return response;
4936
- } catch (error) {
4937
- span.setAttribute("error.type", error.constructor?.name ?? "Error");
4938
- span.setStatus({ code: _opentelemetry_api.SpanStatusCode.ERROR });
4939
- throw error;
4940
- }
4941
- }, true);
4942
- };
4943
- models.generateContentStream = async function(params) {
4944
- if ((0, _opentelemetry_core.isTracingSuppressed)(_opentelemetry_api.context.active())) return originalGenerateContentStream(params);
4945
- const span = Laminar.startSpan({
4946
- name: "gemini.generate_content_stream",
4947
- spanType: "LLM"
4948
- });
4949
- setRequestAttributes$2(span, params, classPatchData.traceContent);
4950
- try {
4951
- return wrapStreamingResponse(span, await originalGenerateContentStream(params), classPatchData.traceContent);
4952
- } catch (error) {
4953
- span.setAttribute("error.type", error.constructor?.name ?? "Error");
4954
- span.recordException(error);
4955
- span.setStatus({ code: _opentelemetry_api.SpanStatusCode.ERROR });
4956
- span.end();
4957
- throw error;
4958
- }
4959
- };
4960
- models[WRAPPED_SYMBOL$1] = true;
5152
+ let ended = false;
5153
+ const fail = (error) => {
5154
+ if (ended) return;
5155
+ ended = true;
5156
+ markSpanError$3(span, error);
5157
+ span.end();
5158
+ };
5159
+ const succeed = (data) => {
5160
+ if (ended) return data;
5161
+ if (params?.stream && isAsyncIterable$3(data)) {
5162
+ ended = true;
5163
+ instrumentStream$2(data, span, traceContent);
5164
+ return data;
5165
+ }
5166
+ ended = true;
5167
+ safely$3(() => setResponseAttributes$4(span, data, traceContent));
5168
+ span.end();
5169
+ return data;
5170
+ };
5171
+ if (typeof result?._thenUnwrap === "function") {
5172
+ const responsePromise = typeof result._responseProps === "function" ? result._responseProps() : result.responsePromise;
5173
+ if (typeof responsePromise?.then === "function") responsePromise.then(void 0, fail);
5174
+ return result._thenUnwrap(succeed);
4961
5175
  }
5176
+ if (typeof result?.then === "function") return result.then(succeed, (error) => {
5177
+ fail(error);
5178
+ throw error;
5179
+ });
5180
+ return succeed(result);
5181
+ };
5182
+ /**
5183
+ * Aggregate the events of an SDK `Stream` as the caller iterates it, and end
5184
+ * the span when iteration finishes. The stream object itself is kept, so
5185
+ * `tee()`, `toReadableStream()` and `controller` keep working.
5186
+ */
5187
+ const instrumentStream$2 = (stream, span, traceContent) => {
5188
+ const originalIterator = stream[Symbol.asyncIterator].bind(stream);
5189
+ const state = createStreamState$1();
5190
+ let ended = false;
5191
+ const end = (error) => {
5192
+ if (ended) return;
5193
+ ended = true;
5194
+ safely$3(() => setStreamingResponseAttributes(span, state, traceContent));
5195
+ if (error !== void 0) markSpanError$3(span, error);
5196
+ else span.setStatus({ code: _opentelemetry_api.SpanStatusCode.OK });
5197
+ span.end();
5198
+ };
5199
+ stream[Symbol.asyncIterator] = async function* () {
5200
+ const iterable = { [Symbol.asyncIterator]: originalIterator };
5201
+ try {
5202
+ for await (const event of iterable) {
5203
+ safely$3(() => processStreamEvent$1(state, event));
5204
+ yield event;
5205
+ }
5206
+ } catch (error) {
5207
+ end(error);
5208
+ throw error;
5209
+ } finally {
5210
+ end();
5211
+ }
5212
+ };
4962
5213
  };
4963
5214
  //#endregion
4964
- //#region src/opentelemetry-lib/instrumentation/kernel.ts
4965
- const WRAPPED_BROWSER_METHODS = [
4966
- "create",
4967
- "retrieve",
4968
- "list",
4969
- "deleteByID",
4970
- "loadExtensions"
4971
- ];
4972
- const WRAPPED_COMPUTER_METHODS = [
4973
- "captureScreenshot",
4974
- "clickMouse",
4975
- "dragMouse",
4976
- "moveMouse",
4977
- "pressKey",
4978
- "scroll",
4979
- "typeText"
4980
- ];
4981
- const WRAPPED_PROCESS_METHODS = [
4982
- "exec",
4983
- "kill",
4984
- "spawn",
4985
- "status",
4986
- "stdin",
4987
- "stdoutStream"
4988
- ];
4989
- var KernelInstrumentation = class extends _opentelemetry_instrumentation.InstrumentationBase {
4990
- constructor() {
4991
- super("@lmnr/kernel-instrumentation", require_utils.version, { enabled: true });
4992
- }
4993
- init() {
4994
- return new _opentelemetry_instrumentation.InstrumentationNodeModuleDefinition("@onkernel/sdk", [">=0.7.0"], this.patch.bind(this), this.unpatch.bind(this));
4995
- }
4996
- manuallyInstrument(kernelModule) {
4997
- for (const wrappedMethod of WRAPPED_BROWSER_METHODS) this._wrap(kernelModule.Kernel.Browsers.prototype, wrappedMethod, this.patchMethod("Browser", wrappedMethod, "DEFAULT"));
4998
- for (const wrappedMethod of WRAPPED_COMPUTER_METHODS) if (wrappedMethod === "captureScreenshot") this._wrap(kernelModule.Kernel.Browsers.Computer.prototype, wrappedMethod, this.patchTakeScreenshot());
4999
- else this._wrap(kernelModule.Kernel.Browsers.Computer.prototype, wrappedMethod, this.patchMethod("Computer", wrappedMethod, "TOOL"));
5000
- for (const wrappedMethod of WRAPPED_PROCESS_METHODS) this._wrap(kernelModule.Kernel.Browsers.Process.prototype, wrappedMethod, this.patchProcessMethod(wrappedMethod));
5001
- this._wrap(kernelModule.Kernel.prototype, "app", this.patchAppFactory());
5215
+ //#region src/opentelemetry-lib/instrumentation/cohere/utils.ts
5216
+ const COHERE_SYSTEM = "cohere";
5217
+ const INPUT_MESSAGES$1 = "gen_ai.input.messages";
5218
+ const OUTPUT_MESSAGES$1 = "gen_ai.output.messages";
5219
+ const OPERATION_NAMES = {
5220
+ chat: "chat",
5221
+ completion: "text_completion",
5222
+ rerank: "rerank",
5223
+ embedding: "embeddings"
5224
+ };
5225
+ const V1_ROLES = {
5226
+ USER: "user",
5227
+ CHATBOT: "assistant",
5228
+ SYSTEM: "system",
5229
+ TOOL: "tool"
5230
+ };
5231
+ const asList = (value) => Array.isArray(value) ? value : [];
5232
+ const asInt = (value) => typeof value === "number" && Number.isFinite(value) ? Math.trunc(value) : void 0;
5233
+ const maybeJson = (value) => {
5234
+ if (typeof value !== "string") return value;
5235
+ try {
5236
+ return JSON.parse(value);
5237
+ } catch {
5238
+ return value;
5002
5239
  }
5003
- patchMethod(className, method, spanType) {
5004
- const plugin = this;
5240
+ };
5241
+ const textPart = (text) => ({
5242
+ type: "text",
5243
+ content: typeof text === "string" ? text : JSON.stringify(text)
5244
+ });
5245
+ const imagePart = (url) => {
5246
+ const comma = url.indexOf(",");
5247
+ if (url.startsWith("data:") && comma !== -1) return {
5248
+ type: "blob",
5249
+ modality: "image",
5250
+ mime_type: url.slice(5, comma).split(";")[0],
5251
+ content: url.slice(comma + 1)
5252
+ };
5253
+ return {
5254
+ type: "uri",
5255
+ modality: "image",
5256
+ uri: url
5257
+ };
5258
+ };
5259
+ /**
5260
+ * Convert v2 message content (a string or a list of content items) into parts.
5261
+ */
5262
+ const contentParts = (content) => {
5263
+ if (typeof content === "string") return content ? [textPart(content)] : [];
5264
+ const parts = [];
5265
+ for (const item of asList(content)) {
5266
+ if (typeof item === "string") {
5267
+ if (item) parts.push(textPart(item));
5268
+ continue;
5269
+ }
5270
+ if (!item || typeof item !== "object") continue;
5271
+ const url = item.imageUrl?.url;
5272
+ if (item.type === "text") parts.push(textPart(item.text ?? ""));
5273
+ else if (item.type === "thinking") parts.push({
5274
+ type: "thinking",
5275
+ content: item.thinking ?? ""
5276
+ });
5277
+ else if (item.type === "image_url" && typeof url === "string") parts.push(imagePart(url));
5278
+ else parts.push(item);
5279
+ }
5280
+ return parts;
5281
+ };
5282
+ /**
5283
+ * v2 tool message content: a string, or a list of text / document items.
5284
+ */
5285
+ const toolResult = (content) => {
5286
+ if (typeof content === "string") return content;
5287
+ const results = asList(content).map((item) => {
5288
+ if (item?.type === "text") return item.text;
5289
+ if (item?.type === "document") return item.document?.data;
5290
+ return item;
5291
+ });
5292
+ return results.length === 1 ? results[0] : results;
5293
+ };
5294
+ const v2ToolCallParts = (toolCalls) => asList(toolCalls).map((toolCall) => {
5295
+ const part = {
5296
+ type: "tool_call",
5297
+ id: toolCall?.id ?? "",
5298
+ name: toolCall?.function?.name ?? ""
5299
+ };
5300
+ const args = toolCall?.function?.arguments;
5301
+ if (args !== void 0 && args !== null) part.arguments = maybeJson(args);
5302
+ return part;
5303
+ });
5304
+ const v1ToolCallParts = (toolCalls) => asList(toolCalls).map((toolCall) => ({
5305
+ type: "tool_call",
5306
+ name: toolCall?.name ?? "",
5307
+ arguments: toolCall?.parameters
5308
+ }));
5309
+ const v1ToolResultParts = (toolResults) => asList(toolResults).map((toolResult) => ({
5310
+ type: "tool_call_response",
5311
+ name: toolResult?.call?.name ?? "",
5312
+ result: toolResult?.outputs
5313
+ }));
5314
+ const v1Message = (message) => {
5315
+ const role = String(message?.role ?? "USER");
5316
+ const parts = [];
5317
+ if (message?.message) parts.push(textPart(message.message));
5318
+ parts.push(...v1ToolCallParts(message?.toolCalls));
5319
+ parts.push(...v1ToolResultParts(message?.toolResults));
5320
+ return {
5321
+ role: V1_ROLES[role.toUpperCase()] ?? role.toLowerCase(),
5322
+ parts
5323
+ };
5324
+ };
5325
+ const v2Message = (message) => {
5326
+ const role = message?.role ?? "user";
5327
+ if (role === "tool") return {
5328
+ role: "tool",
5329
+ parts: [{
5330
+ type: "tool_call_response",
5331
+ id: message?.toolCallId ?? "",
5332
+ result: toolResult(message?.content)
5333
+ }]
5334
+ };
5335
+ const parts = contentParts(message?.content);
5336
+ if (message?.toolPlan) parts.push(textPart(message.toolPlan));
5337
+ parts.push(...v2ToolCallParts(message?.toolCalls));
5338
+ return {
5339
+ role,
5340
+ parts
5341
+ };
5342
+ };
5343
+ const v1ChatInput = (params) => {
5344
+ const messages = [];
5345
+ if (params?.preamble) messages.push({
5346
+ role: "system",
5347
+ parts: [textPart(params.preamble)]
5348
+ });
5349
+ messages.push(...asList(params?.chatHistory).map(v1Message));
5350
+ const toolResults = v1ToolResultParts(params?.toolResults);
5351
+ if (toolResults.length > 0) messages.push({
5352
+ role: "tool",
5353
+ parts: toolResults
5354
+ });
5355
+ if (params?.message) messages.push({
5356
+ role: "user",
5357
+ parts: [textPart(params.message)]
5358
+ });
5359
+ return messages;
5360
+ };
5361
+ const rerankInput = (params) => {
5362
+ const messages = asList(params?.documents).map((document) => {
5363
+ const text = typeof document === "string" ? document : document?.text;
5364
+ return {
5365
+ role: "system",
5366
+ parts: [textPart(text ?? document)]
5367
+ };
5368
+ });
5369
+ if (params?.query) messages.push({
5370
+ role: "user",
5371
+ parts: [textPart(params.query)]
5372
+ });
5373
+ return messages;
5374
+ };
5375
+ const embedInput = (params) => {
5376
+ const parts = [...asList(params?.texts).filter((text) => typeof text === "string").map(textPart), ...asList(params?.images).filter((image) => typeof image === "string").map(imagePart)];
5377
+ for (const input of asList(params?.inputs)) parts.push(...contentParts(input?.content));
5378
+ return parts.length > 0 ? [{
5379
+ role: "user",
5380
+ parts
5381
+ }] : [];
5382
+ };
5383
+ const toolDefinitions = (tools) => asList(tools).map((tool) => {
5384
+ const fn = tool?.function ?? tool;
5385
+ const definition = { name: fn?.name };
5386
+ if (fn?.description) definition.description = fn.description;
5387
+ const parameters = fn?.parameters ?? fn?.parameterDefinitions;
5388
+ if (parameters) definition.parameters = parameters;
5389
+ return definition;
5390
+ });
5391
+ const setRequestAttributes$3 = (span, params, requestType, isV2, isStreaming, traceContent) => {
5392
+ safeSetAttribute$2(span, "gen_ai.system", COHERE_SYSTEM);
5393
+ safeSetAttribute$2(span, "gen_ai.operation.name", OPERATION_NAMES[requestType]);
5394
+ safeSetAttribute$2(span, "gen_ai.request.model", params?.model);
5395
+ safeSetAttribute$2(span, "gen_ai.request.max_tokens", asInt(params?.maxTokens));
5396
+ safeSetAttribute$2(span, "gen_ai.request.temperature", params?.temperature);
5397
+ safeSetAttribute$2(span, "gen_ai.request.top_p", params?.p);
5398
+ safeSetAttribute$2(span, "gen_ai.request.top_k", params?.k);
5399
+ safeSetAttribute$2(span, "gen_ai.request.frequency_penalty", params?.frequencyPenalty);
5400
+ safeSetAttribute$2(span, "gen_ai.request.presence_penalty", params?.presencePenalty);
5401
+ safeSetAttribute$2(span, "gen_ai.request.seed", asInt(params?.seed));
5402
+ safeSetAttribute$2(span, "gen_ai.request.stop_sequences", asList(params?.stopSequences).filter((s) => typeof s === "string"));
5403
+ span.setAttribute("llm.is_streaming", isStreaming);
5404
+ if (!traceContent) return;
5405
+ let messages;
5406
+ if (requestType === "chat") {
5407
+ messages = isV2 ? asList(params?.messages).map(v2Message) : v1ChatInput(params);
5408
+ const tools = toolDefinitions(params?.tools);
5409
+ if (tools.length > 0) span.setAttribute("gen_ai.tool.definitions", JSON.stringify(tools));
5410
+ } else if (requestType === "completion") messages = params?.prompt ? [{
5411
+ role: "user",
5412
+ parts: [textPart(params.prompt)]
5413
+ }] : [];
5414
+ else if (requestType === "rerank") messages = rerankInput(params);
5415
+ else messages = embedInput(params);
5416
+ if (messages.length > 0) span.setAttribute(INPUT_MESSAGES$1, JSON.stringify(messages));
5417
+ };
5418
+ /**
5419
+ * `usage` (v2) / `meta` (v1): actual `tokens`, falling back to `billedUnits`.
5420
+ */
5421
+ const setUsage = (span, usage) => {
5422
+ const inputTokens = asInt(usage?.tokens?.inputTokens) ?? asInt(usage?.billedUnits?.inputTokens);
5423
+ const outputTokens = asInt(usage?.tokens?.outputTokens) ?? asInt(usage?.billedUnits?.outputTokens);
5424
+ safeSetAttribute$2(span, "gen_ai.usage.input_tokens", inputTokens);
5425
+ safeSetAttribute$2(span, "gen_ai.usage.output_tokens", outputTokens);
5426
+ if (inputTokens !== void 0 || outputTokens !== void 0) span.setAttribute("llm.usage.total_tokens", (inputTokens ?? 0) + (outputTokens ?? 0));
5427
+ safeSetAttribute$2(span, "gen_ai.usage.cache_read_input_tokens", asInt(usage?.cachedTokens));
5428
+ };
5429
+ const v1ChatOutput = (response) => {
5430
+ const parts = [];
5431
+ if (response?.text) parts.push(textPart(response.text));
5432
+ parts.push(...v1ToolCallParts(response?.toolCalls));
5433
+ return {
5434
+ role: "assistant",
5435
+ parts
5436
+ };
5437
+ };
5438
+ const v2ChatOutput = (response) => ({
5439
+ ...v2Message(response?.message ?? {}),
5440
+ role: "assistant"
5441
+ });
5442
+ const completionOutput = (response) => asList(response?.generations).map((generation) => ({
5443
+ role: "assistant",
5444
+ parts: [textPart(generation?.text ?? "")]
5445
+ }));
5446
+ const rerankOutput = (response) => {
5447
+ const parts = asList(response?.results).map((result) => {
5448
+ let text = `Doc ${result?.index}, Score: ${result?.relevanceScore}`;
5449
+ if (result?.document?.text) text += `\n${result.document.text}`;
5450
+ return textPart(text);
5451
+ });
5452
+ return parts.length > 0 ? [{
5453
+ role: "assistant",
5454
+ parts
5455
+ }] : [];
5456
+ };
5457
+ const setResponseAttributes$3 = (span, response, requestType, isV2, traceContent) => {
5458
+ safeSetAttribute$2(span, "gen_ai.response.id", response?.responseId ?? response?.id);
5459
+ setUsage(span, response?.usage ?? response?.meta);
5460
+ let output = [];
5461
+ if (requestType === "chat") {
5462
+ const message = isV2 ? v2ChatOutput(response) : v1ChatOutput(response);
5463
+ if (response?.finishReason) {
5464
+ const finishReason = String(response.finishReason);
5465
+ message.finish_reason = finishReason;
5466
+ span.setAttribute("gen_ai.response.finish_reasons", [finishReason]);
5467
+ }
5468
+ output = [message];
5469
+ } else if (requestType === "completion") output = completionOutput(response);
5470
+ else if (requestType === "rerank") output = rerankOutput(response);
5471
+ if (output.length > 0 && traceContent) span.setAttribute(OUTPUT_MESSAGES$1, JSON.stringify(output));
5472
+ };
5473
+ /**
5474
+ * v1 `chatStream`: the `stream-end` event carries the full response.
5475
+ */
5476
+ const createV1ChatStreamAccumulator = () => {
5477
+ let final;
5478
+ let text = "";
5479
+ const toolCalls = [];
5480
+ return {
5481
+ add: (event) => {
5482
+ if (event?.eventType === "text-generation") text += event.text ?? "";
5483
+ else if (event?.eventType === "tool-calls-generation") toolCalls.push(...asList(event.toolCalls));
5484
+ else if (event?.eventType === "stream-end") final = event.response;
5485
+ },
5486
+ response: () => final ?? {
5487
+ text,
5488
+ toolCalls
5489
+ }
5490
+ };
5491
+ };
5492
+ /**
5493
+ * v2 `chatStream`: rebuilds a `V2ChatResponse`-shaped object from the events.
5494
+ */
5495
+ const createV2ChatStreamAccumulator = () => {
5496
+ let id;
5497
+ let toolPlan = "";
5498
+ let finishReason;
5499
+ let usage;
5500
+ const content = /* @__PURE__ */ new Map();
5501
+ const toolCalls = /* @__PURE__ */ new Map();
5502
+ const indexOf = (event, items, isNew) => {
5503
+ if (typeof event?.index === "number") return event.index;
5504
+ if (isNew || items.size === 0) return items.size;
5505
+ return Math.max(...items.keys());
5506
+ };
5507
+ const sorted = (items) => [...items.entries()].sort(([a], [b]) => a - b).map(([, item]) => item);
5508
+ return {
5509
+ add: (event) => {
5510
+ const message = event?.delta?.message;
5511
+ switch (event?.type) {
5512
+ case "message-start":
5513
+ id = event.id ?? id;
5514
+ break;
5515
+ case "content-start":
5516
+ content.set(indexOf(event, content, true), {
5517
+ type: message?.content?.type ?? "text",
5518
+ text: message?.content?.text ?? "",
5519
+ thinking: message?.content?.thinking ?? ""
5520
+ });
5521
+ break;
5522
+ case "content-delta": {
5523
+ const index = indexOf(event, content, false);
5524
+ const item = content.get(index) ?? {
5525
+ type: "text",
5526
+ text: "",
5527
+ thinking: ""
5528
+ };
5529
+ item.text += message?.content?.text ?? "";
5530
+ item.thinking += message?.content?.thinking ?? "";
5531
+ content.set(index, item);
5532
+ break;
5533
+ }
5534
+ case "tool-plan-delta":
5535
+ toolPlan += message?.toolPlan ?? "";
5536
+ break;
5537
+ case "tool-call-start":
5538
+ toolCalls.set(indexOf(event, toolCalls, true), {
5539
+ id: message?.toolCalls?.id ?? "",
5540
+ type: "function",
5541
+ function: {
5542
+ name: message?.toolCalls?.function?.name ?? "",
5543
+ arguments: message?.toolCalls?.function?.arguments ?? ""
5544
+ }
5545
+ });
5546
+ break;
5547
+ case "tool-call-delta": {
5548
+ const index = indexOf(event, toolCalls, false);
5549
+ const toolCall = toolCalls.get(index) ?? {
5550
+ id: "",
5551
+ type: "function",
5552
+ function: {
5553
+ name: "",
5554
+ arguments: ""
5555
+ }
5556
+ };
5557
+ toolCall.function.arguments += message?.toolCalls?.function?.arguments ?? "";
5558
+ toolCalls.set(index, toolCall);
5559
+ break;
5560
+ }
5561
+ case "message-end":
5562
+ id = event.id ?? id;
5563
+ finishReason = event.delta?.finishReason;
5564
+ usage = event.delta?.usage;
5565
+ }
5566
+ },
5567
+ response: () => ({
5568
+ id,
5569
+ finishReason,
5570
+ usage,
5571
+ message: {
5572
+ role: "assistant",
5573
+ content: sorted(content).map((item) => item.type === "thinking" ? {
5574
+ type: "thinking",
5575
+ thinking: item.thinking
5576
+ } : {
5577
+ type: "text",
5578
+ text: item.text
5579
+ }),
5580
+ toolPlan: toolPlan || void 0,
5581
+ toolCalls: sorted(toolCalls)
5582
+ }
5583
+ })
5584
+ };
5585
+ };
5586
+ //#endregion
5587
+ //#region src/opentelemetry-lib/instrumentation/cohere/index.ts
5588
+ const logger$18 = require_utils.initializeLogger();
5589
+ const PATCH_DATA_SYMBOL$2 = Symbol("lmnr.cohere.patchData");
5590
+ const SPAN_NAMES = {
5591
+ chat: "cohere.chat",
5592
+ completion: "cohere.completion",
5593
+ rerank: "cohere.rerank",
5594
+ embedding: "cohere.embed"
5595
+ };
5596
+ const V1_METHODS = [
5597
+ {
5598
+ method: "chat",
5599
+ requestType: "chat",
5600
+ streaming: false
5601
+ },
5602
+ {
5603
+ method: "chatStream",
5604
+ requestType: "chat",
5605
+ streaming: true
5606
+ },
5607
+ {
5608
+ method: "generate",
5609
+ requestType: "completion",
5610
+ streaming: false
5611
+ },
5612
+ {
5613
+ method: "rerank",
5614
+ requestType: "rerank",
5615
+ streaming: false
5616
+ },
5617
+ {
5618
+ method: "embed",
5619
+ requestType: "embedding",
5620
+ streaming: false
5621
+ }
5622
+ ];
5623
+ const V2_METHODS = [
5624
+ {
5625
+ method: "chat",
5626
+ requestType: "chat",
5627
+ streaming: false
5628
+ },
5629
+ {
5630
+ method: "chatStream",
5631
+ requestType: "chat",
5632
+ streaming: true
5633
+ },
5634
+ {
5635
+ method: "rerank",
5636
+ requestType: "rerank",
5637
+ streaming: false
5638
+ },
5639
+ {
5640
+ method: "embed",
5641
+ requestType: "embedding",
5642
+ streaming: false
5643
+ }
5644
+ ];
5645
+ const ownPatchData = (proto) => Object.getOwnPropertyDescriptor(proto, PATCH_DATA_SYMBOL$2)?.value;
5646
+ const markSpanError$2 = (span, error) => {
5647
+ span.recordException(error);
5648
+ span.setAttribute("error.type", error?.constructor?.name ?? "Error");
5649
+ span.setStatus({
5650
+ code: _opentelemetry_api.SpanStatusCode.ERROR,
5651
+ message: error?.message
5652
+ });
5653
+ };
5654
+ /**
5655
+ * Attribute extraction must never break the user's call.
5656
+ */
5657
+ const safely$2 = (fn) => {
5658
+ try {
5659
+ fn();
5660
+ } catch (error) {
5661
+ logger$18.debug(`Failed to set cohere span attributes: ${String(error)}`);
5662
+ }
5663
+ };
5664
+ const isAsyncIterable$2 = (value) => value !== null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function";
5665
+ /**
5666
+ * The prototype in `proto`'s chain that defines `method`, so subclasses
5667
+ * (`CohereClient` is a thin `CustomClient` subclass) share one wrapper.
5668
+ */
5669
+ const definingPrototype = (proto, method) => {
5670
+ for (let p = proto; p && p !== Object.prototype; p = Object.getPrototypeOf(p)) {
5671
+ const descriptor = Object.getOwnPropertyDescriptor(p, method);
5672
+ if (descriptor) return typeof descriptor.value === "function" ? p : void 0;
5673
+ }
5674
+ };
5675
+ /**
5676
+ * Resolve the `cohere-ai` module namespace from the namespace itself or its
5677
+ * default export (ESM default import of the CJS package).
5678
+ */
5679
+ const resolveModule = (mod) => {
5680
+ for (const candidate of [mod, mod?.default]) if (typeof candidate?.CohereClient === "function") return candidate;
5681
+ };
5682
+ /**
5683
+ * `V2Client` is not exported from the package root, so read its prototype
5684
+ * off a throwaway client: `CohereClient#v2` (lazy getter) or
5685
+ * `CohereClientV2#clientV2`. Constructing a client does no I/O.
5686
+ */
5687
+ const v2ClientPrototype = (mod) => {
5688
+ const probes = [() => new mod.CohereClient({ token: "lmnr" }).v2, () => new mod.CohereClientV2({ token: "lmnr" }).clientV2];
5689
+ for (const probe of probes) try {
5690
+ const client = probe();
5691
+ if (client && typeof client === "object") return Object.getPrototypeOf(client);
5692
+ } catch {}
5693
+ };
5694
+ /**
5695
+ * Instruments `cohere-ai`: v1 `chat`, `chatStream`, `generate`, `rerank` and
5696
+ * `embed` on `CohereClient`, and v2 `chat`, `chatStream`, `rerank` and
5697
+ * `embed` on `V2Client` (behind `CohereClientV2` and `CohereClient#v2`).
5698
+ *
5699
+ * `CohereClientV2` binds its methods as instance fields in its constructor,
5700
+ * so clients created before instrumentation are not traced.
5701
+ */
5702
+ var CohereInstrumentation = class extends _opentelemetry_instrumentation.InstrumentationBase {
5703
+ constructor(config) {
5704
+ super("@lmnr/cohere-instrumentation", require_utils.version, { enabled: true });
5705
+ this.traceContent = config?.traceContent ?? true;
5706
+ }
5707
+ init() {
5708
+ return new _opentelemetry_instrumentation.InstrumentationNodeModuleDefinition("cohere-ai", [">=7.0.0"], this.patch.bind(this), this.unpatch.bind(this));
5709
+ }
5710
+ /**
5711
+ * Accepts the `cohere-ai` module namespace (`import * as cohere from
5712
+ * "cohere-ai"`) or its default export.
5713
+ */
5714
+ manuallyInstrument(module) {
5715
+ if (!resolveModule(module)) {
5716
+ _opentelemetry_api.diag.warn("Could not find CohereClient in cohere manual instrumentation input. Pass the cohere-ai module.");
5717
+ return;
5718
+ }
5719
+ _opentelemetry_api.diag.debug("Manually instrumenting cohere-ai");
5720
+ this.patch(module);
5721
+ }
5722
+ patch(moduleExports) {
5723
+ _opentelemetry_api.diag.debug("Patching cohere-ai");
5724
+ for (const { proto, specs, isV2 } of this.targets(moduleExports)) for (const spec of specs) this.patchMethod(definingPrototype(proto, spec.method), spec, isV2);
5725
+ return moduleExports;
5726
+ }
5727
+ unpatch(moduleExports) {
5728
+ _opentelemetry_api.diag.debug("Unpatching cohere-ai");
5729
+ for (const { proto, specs } of this.targets(moduleExports)) for (const { method } of specs) {
5730
+ const owner = definingPrototype(proto, method);
5731
+ const patched = owner && ownPatchData(owner);
5732
+ if (!patched?.[method]) continue;
5733
+ owner[method] = patched[method].original;
5734
+ delete patched[method];
5735
+ }
5736
+ }
5737
+ targets(moduleExports) {
5738
+ const mod = resolveModule(moduleExports);
5739
+ if (!mod) return [];
5740
+ const v1 = mod.CohereClient.prototype;
5741
+ const v2 = v2ClientPrototype(mod);
5742
+ const targets = [{
5743
+ proto: v1,
5744
+ specs: V1_METHODS,
5745
+ isV2: false
5746
+ }];
5747
+ if (v2 && definingPrototype(v2, "chat") !== definingPrototype(v1, "chat")) targets.push({
5748
+ proto: v2,
5749
+ specs: V2_METHODS,
5750
+ isV2: true
5751
+ });
5752
+ return targets;
5753
+ }
5754
+ /**
5755
+ * Replace `proto[method]` with a traced wrapper. Re-patching an already
5756
+ * patched method only refreshes `traceContent`, so repeated initialization
5757
+ * never double-wraps.
5758
+ */
5759
+ patchMethod(proto, spec, isV2) {
5760
+ if (!proto) return;
5761
+ let patched = ownPatchData(proto);
5762
+ if (patched?.[spec.method]) {
5763
+ patched[spec.method].traceContent = this.traceContent;
5764
+ return;
5765
+ }
5766
+ if (!patched) {
5767
+ patched = {};
5768
+ Object.defineProperty(proto, PATCH_DATA_SYMBOL$2, {
5769
+ value: patched,
5770
+ writable: true,
5771
+ configurable: true,
5772
+ enumerable: false
5773
+ });
5774
+ }
5775
+ const patchData = {
5776
+ ...spec,
5777
+ isV2,
5778
+ traceContent: this.traceContent,
5779
+ original: proto[spec.method]
5780
+ };
5781
+ patched[spec.method] = patchData;
5782
+ proto[spec.method] = wrapMethod$1(patchData);
5783
+ }
5784
+ };
5785
+ const wrapMethod$1 = (patchData) => function(request, ...rest) {
5786
+ const { original, requestType, streaming, isV2 } = patchData;
5787
+ if ((0, _opentelemetry_core.isTracingSuppressed)(_opentelemetry_api.context.active())) return original.call(this, request, ...rest);
5788
+ const traceContent = patchData.traceContent;
5789
+ const span = Laminar.startSpan({
5790
+ name: SPAN_NAMES[requestType],
5791
+ spanType: "LLM"
5792
+ });
5793
+ safely$2(() => setRequestAttributes$3(span, request, requestType, isV2, streaming, traceContent));
5794
+ let result;
5795
+ try {
5796
+ result = Laminar.withSpan(span, () => ({ value: original.call(this, request, ...rest) })).value;
5797
+ } catch (error) {
5798
+ markSpanError$2(span, error);
5799
+ span.end();
5800
+ throw error;
5801
+ }
5802
+ let ended = false;
5803
+ const fail = (error) => {
5804
+ if (ended) return;
5805
+ ended = true;
5806
+ markSpanError$2(span, error);
5807
+ span.end();
5808
+ };
5809
+ const succeed = (data) => {
5810
+ if (ended) return data;
5811
+ ended = true;
5812
+ if (streaming && isAsyncIterable$2(data)) {
5813
+ const accumulator = isV2 ? createV2ChatStreamAccumulator() : createV1ChatStreamAccumulator();
5814
+ instrumentStream$1(data, span, accumulator, isV2, traceContent);
5815
+ return data;
5816
+ }
5817
+ safely$2(() => setResponseAttributes$3(span, data, requestType, isV2, traceContent));
5818
+ span.end();
5819
+ return data;
5820
+ };
5821
+ const rethrow = (error) => {
5822
+ fail(error);
5823
+ throw error;
5824
+ };
5825
+ if (typeof result?.withRawResponse === "function" && typeof result.constructor?.fromPromise === "function") return result.constructor.fromPromise(result.withRawResponse().then((raw) => ({
5826
+ ...raw,
5827
+ data: succeed(raw?.data)
5828
+ }), rethrow));
5829
+ if (typeof result?.then === "function") return result.then(succeed, rethrow);
5830
+ return succeed(result);
5831
+ };
5832
+ /**
5833
+ * Aggregate the events of an SDK `Stream` as the caller iterates it, and end
5834
+ * the span when iteration finishes, fails, or is abandoned early.
5835
+ */
5836
+ const instrumentStream$1 = (stream, span, accumulator, isV2, traceContent) => {
5837
+ const originalIterator = stream[Symbol.asyncIterator].bind(stream);
5838
+ let ended = false;
5839
+ const end = (error) => {
5840
+ if (ended) return;
5841
+ ended = true;
5842
+ safely$2(() => setResponseAttributes$3(span, accumulator.response(), "chat", isV2, traceContent));
5843
+ if (error !== void 0) markSpanError$2(span, error);
5844
+ else span.setStatus({ code: _opentelemetry_api.SpanStatusCode.OK });
5845
+ span.end();
5846
+ };
5847
+ stream[Symbol.asyncIterator] = async function* () {
5848
+ const iterable = { [Symbol.asyncIterator]: originalIterator };
5849
+ try {
5850
+ for await (const event of iterable) {
5851
+ safely$2(() => accumulator.add(event));
5852
+ yield event;
5853
+ }
5854
+ } catch (error) {
5855
+ end(error);
5856
+ throw error;
5857
+ } finally {
5858
+ end();
5859
+ }
5860
+ };
5861
+ };
5862
+ //#endregion
5863
+ //#region src/opentelemetry-lib/instrumentation/google-aiplatform/utils.ts
5864
+ const VERTEX_AI_SYSTEM = "vertex_ai";
5865
+ const VALUE_KINDS = [
5866
+ "stringValue",
5867
+ "numberValue",
5868
+ "boolValue",
5869
+ "structValue",
5870
+ "listValue",
5871
+ "nullValue"
5872
+ ];
5873
+ /**
5874
+ * Decode a `google.protobuf.Value` (either a protobufjs message instance or
5875
+ * a plain object, e.g. produced by `aiplatform.helpers.toValue`) into a plain
5876
+ * JS value. Unset oneof members on protobufjs messages default to `null`, so
5877
+ * we prefer the `kind` virtual field when it is available.
5878
+ */
5879
+ const fromValue = (value) => {
5880
+ if (value === null || value === void 0 || typeof value !== "object") return value;
5881
+ const kind = typeof value.kind === "string" ? value.kind : VALUE_KINDS.find((k) => value[k] !== void 0 && value[k] !== null);
5882
+ switch (kind) {
5883
+ case "stringValue":
5884
+ case "numberValue":
5885
+ case "boolValue": return value[kind];
5886
+ case "structValue": return Object.fromEntries(Object.entries(value.structValue?.fields ?? {}).map(([k, v]) => [k, fromValue(v)]));
5887
+ case "listValue": return (value.listValue?.values ?? []).map(fromValue);
5888
+ case "nullValue": return null;
5889
+ default: return;
5890
+ }
5891
+ };
5892
+ const asRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
5893
+ const asNumber = (value) => typeof value === "number" && !Number.isNaN(value) ? value : void 0;
5894
+ /**
5895
+ * Strip resource prefixes, e.g.
5896
+ * `projects/p/locations/l/publishers/google/models/text-bison` -> `text-bison`.
5897
+ */
5898
+ const lastPathSegment = (value) => {
5899
+ if (typeof value !== "string" || value.length === 0) return void 0;
5900
+ return value.split("/").pop() || void 0;
5901
+ };
5902
+ const toInputMessages = (instance) => {
5903
+ const messages = [];
5904
+ if (typeof instance.context === "string" && instance.context.length > 0) messages.push({
5905
+ role: "system",
5906
+ content: instance.context
5907
+ });
5908
+ if (typeof instance.prompt === "string") messages.push({
5909
+ role: "user",
5910
+ content: instance.prompt
5911
+ });
5912
+ if (Array.isArray(instance.messages)) for (const message of instance.messages) {
5913
+ const record = asRecord(message);
5914
+ if (!record) continue;
5915
+ const author = typeof record.author === "string" ? record.author : "user";
5916
+ messages.push({
5917
+ role: author === "bot" ? "assistant" : author,
5918
+ content: record.content
5919
+ });
5920
+ }
5921
+ return messages;
5922
+ };
5923
+ /**
5924
+ * Set request attributes on a span from a `PredictionServiceClient.predict`
5925
+ * request (PaLM-style text / chat models served through Vertex AI).
5926
+ */
5927
+ const setPredictRequestAttributes = (span, request, traceContent) => {
5928
+ safeSetAttribute$2(span, "gen_ai.system", VERTEX_AI_SYSTEM);
5929
+ safeSetAttribute$2(span, "gen_ai.request.model", lastPathSegment(request?.endpoint));
5930
+ const parameters = asRecord(fromValue(request?.parameters));
5931
+ if (parameters) {
5932
+ safeSetAttribute$2(span, "gen_ai.request.max_tokens", asNumber(parameters.maxOutputTokens));
5933
+ safeSetAttribute$2(span, "gen_ai.request.temperature", asNumber(parameters.temperature));
5934
+ safeSetAttribute$2(span, "gen_ai.request.top_p", asNumber(parameters.topP));
5935
+ safeSetAttribute$2(span, "gen_ai.request.top_k", asNumber(parameters.topK));
5936
+ }
5937
+ if (!traceContent || !Array.isArray(request?.instances)) return;
5938
+ const messages = request.instances.flatMap((instance) => {
5939
+ const record = asRecord(fromValue(instance));
5940
+ return record ? toInputMessages(record) : [];
5941
+ });
5942
+ if (messages.length > 0) safeSetAttribute$2(span, "gen_ai.input.messages", JSON.stringify(messages));
5943
+ };
5944
+ const predictionContent = (prediction) => {
5945
+ const record = asRecord(fromValue(prediction));
5946
+ if (!record) return void 0;
5947
+ if (typeof record.content === "string") return record.content;
5948
+ const firstCandidate = Array.isArray(record.candidates) ? asRecord(record.candidates[0]) : void 0;
5949
+ if (typeof firstCandidate?.content === "string") return firstCandidate.content;
5950
+ };
5951
+ /**
5952
+ * Set response attributes on a span from a `PredictResponse`.
5953
+ */
5954
+ const setPredictResponseAttributes = (span, response, traceContent) => {
5955
+ if (!response) return;
5956
+ safeSetAttribute$2(span, "gen_ai.response.model", lastPathSegment(response.model));
5957
+ const metadata = asRecord(fromValue(response.metadata));
5958
+ const tokenMetadata = asRecord(metadata?.tokenMetadata);
5959
+ const inputTokens = asNumber(asRecord(tokenMetadata?.inputTokenCount)?.totalTokens);
5960
+ const outputTokens = asNumber(asRecord(tokenMetadata?.outputTokenCount)?.totalTokens);
5961
+ safeSetAttribute$2(span, "gen_ai.usage.input_tokens", inputTokens);
5962
+ safeSetAttribute$2(span, "gen_ai.usage.output_tokens", outputTokens);
5963
+ if (inputTokens !== void 0 && outputTokens !== void 0) safeSetAttribute$2(span, "llm.usage.total_tokens", inputTokens + outputTokens);
5964
+ if (!traceContent || !Array.isArray(response.predictions)) return;
5965
+ const outputMessages = response.predictions.map(predictionContent).filter((content) => content !== void 0).map((content) => ({
5966
+ role: "assistant",
5967
+ content
5968
+ }));
5969
+ if (outputMessages.length > 0) safeSetAttribute$2(span, "gen_ai.output.messages", JSON.stringify(outputMessages));
5970
+ };
5971
+ /**
5972
+ * Reshape a Vertex AI `GenerativeModel` request into the
5973
+ * `{model, contents, config}` form the google-genai helpers understand.
5974
+ * Request-level `generationConfig`, `systemInstruction`, and `tools` fully
5975
+ * override the model-level ones, mirroring the Vertex AI SDK.
5976
+ */
5977
+ const toGenAiParams = (model, request) => {
5978
+ const isStringRequest = typeof request === "string";
5979
+ const req = isStringRequest ? {} : request ?? {};
5980
+ return {
5981
+ model: lastPathSegment(model?.model),
5982
+ contents: isStringRequest ? request : req.contents,
5983
+ config: {
5984
+ ...req.generationConfig ?? model?.generationConfig ?? {},
5985
+ systemInstruction: req.systemInstruction ?? model?.systemInstruction,
5986
+ tools: req.tools ?? model?.tools
5987
+ }
5988
+ };
5989
+ };
5990
+ //#endregion
5991
+ //#region src/opentelemetry-lib/instrumentation/google-aiplatform/index.ts
5992
+ const logger$17 = require_utils.initializeLogger();
5993
+ const PATCH_DATA_SYMBOL$1 = Symbol("lmnr.google-aiplatform.patchData");
5994
+ const hasOwnPatchData$1 = (proto) => Object.getOwnPropertyDescriptor(proto, PATCH_DATA_SYMBOL$1) !== void 0;
5995
+ const GENERATIVE_MODEL_CLASSES = ["GenerativeModel", "GenerativeModelPreview"];
5996
+ const markSpanError$1 = (span, error) => {
5997
+ span.setAttribute("error.type", error?.constructor?.name ?? "Error");
5998
+ span.setStatus({ code: _opentelemetry_api.SpanStatusCode.ERROR });
5999
+ };
6000
+ /**
6001
+ * Attribute extraction must never break the user's call.
6002
+ */
6003
+ const safely$1 = (fn) => {
6004
+ try {
6005
+ fn();
6006
+ } catch (error) {
6007
+ logger$17.debug(`Failed to set google-aiplatform span attributes: ${String(error)}`);
6008
+ }
6009
+ };
6010
+ /**
6011
+ * Instruments Google Cloud Vertex AI:
6012
+ * - `@google-cloud/vertexai`: `GenerativeModel` (and `GenerativeModelPreview`)
6013
+ * `generateContent` / `generateContentStream`.
6014
+ * - `@google-cloud/aiplatform`: `PredictionServiceClient.predict`.
6015
+ */
6016
+ var GoogleAIPlatformInstrumentation = class extends _opentelemetry_instrumentation.InstrumentationBase {
6017
+ constructor(config) {
6018
+ super("@lmnr/google-aiplatform-instrumentation", require_utils.version, { enabled: true });
6019
+ this.traceContent = config?.traceContent ?? true;
6020
+ }
6021
+ init() {
6022
+ return [new _opentelemetry_instrumentation.InstrumentationNodeModuleDefinition("@google-cloud/vertexai", [">=1.1.0"], this.patchVertexAI.bind(this), this.unpatchVertexAI.bind(this)), new _opentelemetry_instrumentation.InstrumentationNodeModuleDefinition("@google-cloud/aiplatform", [">=3.10.0"], this.patchAIPlatform.bind(this), this.unpatchAIPlatform.bind(this))];
6023
+ }
6024
+ /**
6025
+ * Accepts the `@google-cloud/vertexai` module (or its `GenerativeModel`
6026
+ * class) and/or the `@google-cloud/aiplatform` module (or its
6027
+ * `PredictionServiceClient` class).
6028
+ */
6029
+ manuallyInstrument(module) {
6030
+ const modules = Array.isArray(module) ? module : [module];
6031
+ for (const mod of modules) if (this.isVertexAIModule(mod)) {
6032
+ _opentelemetry_api.diag.debug("Manually instrumenting @google-cloud/vertexai");
6033
+ this.patchVertexAI(mod);
6034
+ } else if (this.isAIPlatformModule(mod)) {
6035
+ _opentelemetry_api.diag.debug("Manually instrumenting @google-cloud/aiplatform");
6036
+ this.patchAIPlatform(mod);
6037
+ } else if (typeof mod?.prototype?.generateContent === "function") {
6038
+ _opentelemetry_api.diag.debug("Manually instrumenting Vertex AI GenerativeModel class");
6039
+ this.patchGenerativeModelClass(mod);
6040
+ } else if (typeof mod?.prototype?.predict === "function") {
6041
+ _opentelemetry_api.diag.debug("Manually instrumenting PredictionServiceClient class");
6042
+ this.patchPredictionServiceClass(mod);
6043
+ } else _opentelemetry_api.diag.warn("Could not find GenerativeModel or PredictionServiceClient in google_aiplatform manual instrumentation input. Pass the @google-cloud/vertexai or @google-cloud/aiplatform module.");
6044
+ }
6045
+ isVertexAIModule(mod) {
6046
+ return typeof mod?.GenerativeModel === "function";
6047
+ }
6048
+ isAIPlatformModule(mod) {
6049
+ return typeof mod?.PredictionServiceClient === "function";
6050
+ }
6051
+ patchVertexAI(moduleExports) {
6052
+ _opentelemetry_api.diag.debug("Patching @google-cloud/vertexai");
6053
+ for (const className of GENERATIVE_MODEL_CLASSES) {
6054
+ const cls = moduleExports?.[className];
6055
+ if (typeof cls === "function") this.patchGenerativeModelClass(cls);
6056
+ }
6057
+ return moduleExports;
6058
+ }
6059
+ unpatchVertexAI(moduleExports) {
6060
+ _opentelemetry_api.diag.debug("Unpatching @google-cloud/vertexai");
6061
+ for (const className of GENERATIVE_MODEL_CLASSES) {
6062
+ const cls = moduleExports?.[className];
6063
+ if (typeof cls === "function") this.unpatchMethods(cls.prototype);
6064
+ }
6065
+ }
6066
+ patchAIPlatform(moduleExports) {
6067
+ _opentelemetry_api.diag.debug("Patching @google-cloud/aiplatform");
6068
+ for (const cls of this.predictionServiceClasses(moduleExports)) this.patchPredictionServiceClass(cls);
6069
+ return moduleExports;
6070
+ }
6071
+ unpatchAIPlatform(moduleExports) {
6072
+ _opentelemetry_api.diag.debug("Unpatching @google-cloud/aiplatform");
6073
+ for (const cls of this.predictionServiceClasses(moduleExports)) this.unpatchMethods(cls.prototype);
6074
+ }
6075
+ predictionServiceClasses(moduleExports) {
6076
+ const classes = [
6077
+ moduleExports?.PredictionServiceClient,
6078
+ moduleExports?.v1?.PredictionServiceClient,
6079
+ moduleExports?.v1beta1?.PredictionServiceClient
6080
+ ].filter((cls) => typeof cls === "function");
6081
+ return [...new Set(classes)];
6082
+ }
6083
+ patchGenerativeModelClass(cls) {
6084
+ this.patchMethod(cls.prototype, "generateContent", (original, data) => this.wrapGenerateContent(original, data));
6085
+ this.patchMethod(cls.prototype, "generateContentStream", (original, data) => this.wrapGenerateContentStream(original, data));
6086
+ }
6087
+ patchPredictionServiceClass(cls) {
6088
+ this.patchMethod(cls.prototype, "predict", (original, data) => this.wrapPredict(original, data));
6089
+ }
6090
+ /**
6091
+ * Replace `proto[method]` with a traced wrapper. Re-patching an already
6092
+ * patched prototype only refreshes `traceContent`, so repeated
6093
+ * initialization never double-wraps.
6094
+ */
6095
+ patchMethod(proto, method, makeWrapper) {
6096
+ if (!proto || typeof proto[method] !== "function") return;
6097
+ if (!hasOwnPatchData$1(proto)) Object.defineProperty(proto, PATCH_DATA_SYMBOL$1, {
6098
+ value: {},
6099
+ writable: true,
6100
+ configurable: true,
6101
+ enumerable: false
6102
+ });
6103
+ const patches = proto[PATCH_DATA_SYMBOL$1];
6104
+ const existing = patches[method];
6105
+ if (existing) {
6106
+ existing.traceContent = this.traceContent;
6107
+ return;
6108
+ }
6109
+ const patchData = {
6110
+ traceContent: this.traceContent,
6111
+ original: proto[method]
6112
+ };
6113
+ patches[method] = patchData;
6114
+ proto[method] = makeWrapper(patchData.original, patchData);
6115
+ }
6116
+ unpatchMethods(proto) {
6117
+ if (!proto || !hasOwnPatchData$1(proto)) return;
6118
+ const patches = proto[PATCH_DATA_SYMBOL$1];
6119
+ for (const [method, patchData] of Object.entries(patches)) proto[method] = patchData.original;
6120
+ delete proto[PATCH_DATA_SYMBOL$1];
6121
+ }
6122
+ wrapGenerateContent(original, patchData) {
6123
+ return function(request, ...rest) {
6124
+ if ((0, _opentelemetry_core.isTracingSuppressed)(_opentelemetry_api.context.active())) return original.call(this, request, ...rest);
6125
+ const span = Laminar.startSpan({
6126
+ name: "vertexai.generate_content",
6127
+ spanType: "LLM"
6128
+ });
6129
+ const params = toGenAiParams(this, request);
6130
+ safely$1(() => setRequestAttributes$5(span, params, patchData.traceContent, VERTEX_AI_SYSTEM));
6131
+ return Laminar.withSpan(span, async () => {
6132
+ try {
6133
+ const result = await original.call(this, request, ...rest);
6134
+ safely$1(() => setGenerateContentResponseAttributes(span, result?.response, params.model, patchData.traceContent));
6135
+ return result;
6136
+ } catch (error) {
6137
+ markSpanError$1(span, error);
6138
+ throw error;
6139
+ }
6140
+ }, true);
6141
+ };
6142
+ }
6143
+ wrapGenerateContentStream(original, patchData) {
6144
+ return async function(request, ...rest) {
6145
+ if ((0, _opentelemetry_core.isTracingSuppressed)(_opentelemetry_api.context.active())) return original.call(this, request, ...rest);
6146
+ const span = Laminar.startSpan({
6147
+ name: "vertexai.generate_content_stream",
6148
+ spanType: "LLM"
6149
+ });
6150
+ const params = toGenAiParams(this, request);
6151
+ safely$1(() => setRequestAttributes$5(span, params, patchData.traceContent, VERTEX_AI_SYSTEM));
6152
+ let result;
6153
+ try {
6154
+ result = await Laminar.withSpan(span, () => original.call(this, request, ...rest));
6155
+ } catch (error) {
6156
+ markSpanError$1(span, error);
6157
+ span.end();
6158
+ throw error;
6159
+ }
6160
+ const aggregated = result?.response;
6161
+ if (aggregated && typeof aggregated.then === "function") aggregated.then((response) => {
6162
+ safely$1(() => setGenerateContentResponseAttributes(span, response, params.model, patchData.traceContent));
6163
+ span.end();
6164
+ }, (error) => {
6165
+ span.recordException(error);
6166
+ markSpanError$1(span, error);
6167
+ span.end();
6168
+ });
6169
+ else span.end();
6170
+ return result;
6171
+ };
6172
+ }
6173
+ wrapPredict(original, patchData) {
6174
+ return function(...args) {
6175
+ if ((0, _opentelemetry_core.isTracingSuppressed)(_opentelemetry_api.context.active())) return original.apply(this, args);
6176
+ const span = Laminar.startSpan({
6177
+ name: "aiplatform.predict",
6178
+ spanType: "LLM"
6179
+ });
6180
+ safely$1(() => setPredictRequestAttributes(span, args[0], patchData.traceContent));
6181
+ const callbackIndex = args.length - 1;
6182
+ const callback = args[callbackIndex];
6183
+ if (typeof callback === "function") {
6184
+ const wrappedArgs = [...args];
6185
+ wrappedArgs[callbackIndex] = function(error, response, ...rest) {
6186
+ if (error) {
6187
+ span.recordException(error);
6188
+ markSpanError$1(span, error);
6189
+ } else safely$1(() => setPredictResponseAttributes(span, response, patchData.traceContent));
6190
+ span.end();
6191
+ return callback.call(this, error, response, ...rest);
6192
+ };
6193
+ try {
6194
+ return Laminar.withSpan(span, () => original.apply(this, wrappedArgs));
6195
+ } catch (error) {
6196
+ markSpanError$1(span, error);
6197
+ span.end();
6198
+ throw error;
6199
+ }
6200
+ }
6201
+ return Laminar.withSpan(span, async () => {
6202
+ try {
6203
+ const result = await original.apply(this, args);
6204
+ safely$1(() => setPredictResponseAttributes(span, Array.isArray(result) ? result[0] : result, patchData.traceContent));
6205
+ return result;
6206
+ } catch (error) {
6207
+ markSpanError$1(span, error);
6208
+ throw error;
6209
+ }
6210
+ }, true);
6211
+ };
6212
+ }
6213
+ };
6214
+ const setGenerateContentResponseAttributes = (span, response, requestModel, traceContent) => {
6215
+ setResponseAttributes$5(span, response, traceContent);
6216
+ if (!response?.modelVersion) safeSetAttribute$2(span, "gen_ai.response.model", requestModel);
6217
+ };
6218
+ //#endregion
6219
+ //#region src/opentelemetry-lib/instrumentation/google-genai/index.ts
6220
+ const WRAPPED_SYMBOL$1 = Symbol("lmnr.google-genai.wrapped");
6221
+ const CLASS_PATCH_DATA_SYMBOL = Symbol("lmnr.google-genai.classPatchData");
6222
+ var GoogleGenAiInstrumentation = class extends _opentelemetry_instrumentation.InstrumentationBase {
6223
+ constructor(config) {
6224
+ super("@lmnr/google-genai-instrumentation", require_utils.version, { enabled: true });
6225
+ this.traceContent = config?.traceContent ?? true;
6226
+ }
6227
+ init() {
6228
+ return new _opentelemetry_instrumentation.InstrumentationNodeModuleDefinition("@google/genai", [">=1.0.0"], this.patch.bind(this), this.unpatch.bind(this));
6229
+ }
6230
+ manuallyInstrument(genaiModule) {
6231
+ _opentelemetry_api.diag.debug("Manually instrumenting @google/genai");
6232
+ const GoogleGenAIClass = this.resolveGoogleGenAIClass(genaiModule);
6233
+ if (GoogleGenAIClass) this.patchGoogleGenAIClass(GoogleGenAIClass);
6234
+ else _opentelemetry_api.diag.warn("Could not find GoogleGenAI class in google_genai manual instrumentation input. Pass either GoogleGenAI class or module object with GoogleGenAI export.");
6235
+ }
6236
+ patch(moduleExports) {
6237
+ _opentelemetry_api.diag.debug("Patching @google/genai");
6238
+ const GoogleGenAIClass = this.resolveGoogleGenAIClass(moduleExports);
6239
+ if (GoogleGenAIClass) this.patchGoogleGenAIClass(GoogleGenAIClass);
6240
+ return moduleExports;
6241
+ }
6242
+ unpatch(moduleExports) {
6243
+ _opentelemetry_api.diag.debug("Unpatching @google/genai");
6244
+ const GoogleGenAIClass = this.resolveGoogleGenAIClass(moduleExports);
6245
+ if (GoogleGenAIClass) this.unpatchGoogleGenAIClass(GoogleGenAIClass);
6246
+ }
6247
+ resolveGoogleGenAIClass(moduleOrClass) {
6248
+ if (typeof moduleOrClass === "function") return moduleOrClass;
6249
+ if (moduleOrClass?.GoogleGenAI && typeof moduleOrClass.GoogleGenAI === "function") return moduleOrClass.GoogleGenAI;
6250
+ }
6251
+ patchGoogleGenAIClass(GoogleGenAIClass) {
6252
+ const classPatchData = GoogleGenAIClass[CLASS_PATCH_DATA_SYMBOL];
6253
+ if (classPatchData) {
6254
+ classPatchData.instrumentation = this;
6255
+ classPatchData.traceContent = this.traceContent;
6256
+ return;
6257
+ }
6258
+ const originalModelsDescriptor = Object.getOwnPropertyDescriptor(GoogleGenAIClass.prototype, "models");
6259
+ if (originalModelsDescriptor && !originalModelsDescriptor.configurable) {
6260
+ _opentelemetry_api.diag.warn("Could not patch GoogleGenAI.prototype.models: descriptor is non-configurable.");
6261
+ return;
6262
+ }
6263
+ const patchData = {
6264
+ instrumentation: this,
6265
+ traceContent: this.traceContent,
6266
+ originalModelsDescriptor
6267
+ };
6268
+ Object.defineProperty(GoogleGenAIClass, CLASS_PATCH_DATA_SYMBOL, {
6269
+ value: patchData,
6270
+ writable: true,
6271
+ configurable: true,
6272
+ enumerable: false
6273
+ });
6274
+ Object.defineProperty(GoogleGenAIClass.prototype, "models", {
6275
+ configurable: true,
6276
+ enumerable: originalModelsDescriptor?.enumerable ?? true,
6277
+ get: function() {
6278
+ if (originalModelsDescriptor?.get) return originalModelsDescriptor.get.call(this);
6279
+ },
6280
+ set: function(value) {
6281
+ patchData.instrumentation.patchModelsInstance(value, patchData);
6282
+ if (originalModelsDescriptor?.set) {
6283
+ originalModelsDescriptor.set.call(this, value);
6284
+ return;
6285
+ }
6286
+ Object.defineProperty(this, "models", {
6287
+ value,
6288
+ writable: true,
6289
+ configurable: true,
6290
+ enumerable: true
6291
+ });
6292
+ }
6293
+ });
6294
+ }
6295
+ unpatchGoogleGenAIClass(GoogleGenAIClass) {
6296
+ const classPatchData = GoogleGenAIClass[CLASS_PATCH_DATA_SYMBOL];
6297
+ if (!classPatchData) return;
6298
+ if (classPatchData.originalModelsDescriptor) Object.defineProperty(GoogleGenAIClass.prototype, "models", classPatchData.originalModelsDescriptor);
6299
+ else delete GoogleGenAIClass.prototype.models;
6300
+ delete GoogleGenAIClass[CLASS_PATCH_DATA_SYMBOL];
6301
+ }
6302
+ patchModelsInstance(models, classPatchData) {
6303
+ if (!models || typeof models !== "object") return;
6304
+ if (typeof models.generateContent !== "function") return;
6305
+ if (typeof models.generateContentStream !== "function") return;
6306
+ if (models[WRAPPED_SYMBOL$1]) return;
6307
+ const originalGenerateContent = models.generateContent.bind(models);
6308
+ const originalGenerateContentStream = models.generateContentStream.bind(models);
6309
+ models.generateContent = async function(params) {
6310
+ if ((0, _opentelemetry_core.isTracingSuppressed)(_opentelemetry_api.context.active())) return originalGenerateContent(params);
6311
+ const span = Laminar.startSpan({
6312
+ name: "gemini.generate_content",
6313
+ spanType: "LLM"
6314
+ });
6315
+ setRequestAttributes$5(span, params, classPatchData.traceContent);
6316
+ return Laminar.withSpan(span, async () => {
6317
+ try {
6318
+ const response = await originalGenerateContent(params);
6319
+ setResponseAttributes$5(span, response, classPatchData.traceContent);
6320
+ return response;
6321
+ } catch (error) {
6322
+ span.setAttribute("error.type", error.constructor?.name ?? "Error");
6323
+ span.setStatus({ code: _opentelemetry_api.SpanStatusCode.ERROR });
6324
+ throw error;
6325
+ }
6326
+ }, true);
6327
+ };
6328
+ models.generateContentStream = async function(params) {
6329
+ if ((0, _opentelemetry_core.isTracingSuppressed)(_opentelemetry_api.context.active())) return originalGenerateContentStream(params);
6330
+ const span = Laminar.startSpan({
6331
+ name: "gemini.generate_content_stream",
6332
+ spanType: "LLM"
6333
+ });
6334
+ setRequestAttributes$5(span, params, classPatchData.traceContent);
6335
+ try {
6336
+ return wrapStreamingResponse(span, await originalGenerateContentStream(params), classPatchData.traceContent);
6337
+ } catch (error) {
6338
+ span.setAttribute("error.type", error.constructor?.name ?? "Error");
6339
+ span.recordException(error);
6340
+ span.setStatus({ code: _opentelemetry_api.SpanStatusCode.ERROR });
6341
+ span.end();
6342
+ throw error;
6343
+ }
6344
+ };
6345
+ models[WRAPPED_SYMBOL$1] = true;
6346
+ }
6347
+ };
6348
+ //#endregion
6349
+ //#region src/opentelemetry-lib/instrumentation/kernel.ts
6350
+ const WRAPPED_BROWSER_METHODS = [
6351
+ "create",
6352
+ "retrieve",
6353
+ "list",
6354
+ "deleteByID",
6355
+ "loadExtensions"
6356
+ ];
6357
+ const WRAPPED_COMPUTER_METHODS = [
6358
+ "captureScreenshot",
6359
+ "clickMouse",
6360
+ "dragMouse",
6361
+ "moveMouse",
6362
+ "pressKey",
6363
+ "scroll",
6364
+ "typeText"
6365
+ ];
6366
+ const WRAPPED_PROCESS_METHODS = [
6367
+ "exec",
6368
+ "kill",
6369
+ "spawn",
6370
+ "status",
6371
+ "stdin",
6372
+ "stdoutStream"
6373
+ ];
6374
+ var KernelInstrumentation = class extends _opentelemetry_instrumentation.InstrumentationBase {
6375
+ constructor() {
6376
+ super("@lmnr/kernel-instrumentation", require_utils.version, { enabled: true });
6377
+ }
6378
+ init() {
6379
+ return new _opentelemetry_instrumentation.InstrumentationNodeModuleDefinition("@onkernel/sdk", [">=0.7.0"], this.patch.bind(this), this.unpatch.bind(this));
6380
+ }
6381
+ manuallyInstrument(kernelModule) {
6382
+ for (const wrappedMethod of WRAPPED_BROWSER_METHODS) this._wrap(kernelModule.Kernel.Browsers.prototype, wrappedMethod, this.patchMethod("Browser", wrappedMethod, "DEFAULT"));
6383
+ for (const wrappedMethod of WRAPPED_COMPUTER_METHODS) if (wrappedMethod === "captureScreenshot") this._wrap(kernelModule.Kernel.Browsers.Computer.prototype, wrappedMethod, this.patchTakeScreenshot());
6384
+ else this._wrap(kernelModule.Kernel.Browsers.Computer.prototype, wrappedMethod, this.patchMethod("Computer", wrappedMethod, "TOOL"));
6385
+ for (const wrappedMethod of WRAPPED_PROCESS_METHODS) this._wrap(kernelModule.Kernel.Browsers.Process.prototype, wrappedMethod, this.patchProcessMethod(wrappedMethod));
6386
+ this._wrap(kernelModule.Kernel.prototype, "app", this.patchAppFactory());
6387
+ }
6388
+ patchMethod(className, method, spanType) {
6389
+ const plugin = this;
5005
6390
  return (original) => async function(...args) {
5006
6391
  return await observe({
5007
6392
  name: `${className}.${method}`,
@@ -5096,100 +6481,950 @@ var KernelInstrumentation = class extends _opentelemetry_instrumentation.Instrum
5096
6481
  this.manuallyInstrument(moduleExports);
5097
6482
  return moduleExports;
5098
6483
  }
5099
- unpatch(moduleExports) {
5100
- _opentelemetry_api.diag.debug("Unpatching @onkernel/sdk");
5101
- for (const wrappedMethod of WRAPPED_BROWSER_METHODS) this._unwrap(moduleExports.Kernel.Browsers.prototype, wrappedMethod);
5102
- for (const wrappedMethod of WRAPPED_COMPUTER_METHODS) this._unwrap(moduleExports.Kernel.Browsers.Computer.prototype, wrappedMethod);
5103
- for (const wrappedMethod of WRAPPED_PROCESS_METHODS) this._unwrap(moduleExports.Kernel.Browsers.Process.prototype, wrappedMethod);
5104
- this._unwrap(moduleExports.Kernel.prototype, "app");
6484
+ unpatch(moduleExports) {
6485
+ _opentelemetry_api.diag.debug("Unpatching @onkernel/sdk");
6486
+ for (const wrappedMethod of WRAPPED_BROWSER_METHODS) this._unwrap(moduleExports.Kernel.Browsers.prototype, wrappedMethod);
6487
+ for (const wrappedMethod of WRAPPED_COMPUTER_METHODS) this._unwrap(moduleExports.Kernel.Browsers.Computer.prototype, wrappedMethod);
6488
+ for (const wrappedMethod of WRAPPED_PROCESS_METHODS) this._unwrap(moduleExports.Kernel.Browsers.Process.prototype, wrappedMethod);
6489
+ this._unwrap(moduleExports.Kernel.prototype, "app");
6490
+ }
6491
+ };
6492
+ const DISABLE_OPENAI_RESPONSES_INSTRUMENTATION_CONTEXT_KEY = (0, _opentelemetry_api.createContextKey)("LMNR_DISABLE_OPENAI_RESPONSES_INSTRUMENTATION");
6493
+ const systemInstructionsStorage = new async_hooks.AsyncLocalStorage();
6494
+ const getCurrentSystemInstructions = () => systemInstructionsStorage.getStore();
6495
+ const runWithSystemInstructions = (value, fn) => systemInstructionsStorage.run(value, fn);
6496
+ const wrapStreamWithSystemInstructions = (value, source) => ({ [Symbol.asyncIterator]() {
6497
+ let iterator;
6498
+ const getIterator = () => {
6499
+ if (iterator === void 0) iterator = systemInstructionsStorage.run(value, () => source[Symbol.asyncIterator]());
6500
+ return iterator;
6501
+ };
6502
+ return {
6503
+ next: (..._args) => systemInstructionsStorage.run(value, () => getIterator().next()),
6504
+ return: (returnValue) => {
6505
+ const it = getIterator();
6506
+ return it.return ? systemInstructionsStorage.run(value, () => it.return(returnValue)) : Promise.resolve({
6507
+ done: true,
6508
+ value: returnValue
6509
+ });
6510
+ },
6511
+ throw: (err) => {
6512
+ const it = getIterator();
6513
+ return it.throw ? systemInstructionsStorage.run(value, () => it.throw(err)) : Promise.reject(err);
6514
+ }
6515
+ };
6516
+ } });
6517
+ const spanKind = (spanData) => {
6518
+ if (spanData == null) return "";
6519
+ return typeof spanData.type === "string" ? spanData.type : "";
6520
+ };
6521
+ const spanName = (span, spanData) => {
6522
+ const name = span?.name;
6523
+ if (typeof name === "string" && name) return name;
6524
+ const kind = spanKind(spanData);
6525
+ if (kind) {
6526
+ if (kind === "agent" || kind === "custom" || kind === "function" || kind === "tool") return nameFromSpanData(spanData) || `agents.${kind}`;
6527
+ return `agents.${kind}`;
6528
+ }
6529
+ return "agents.span";
6530
+ };
6531
+ const mapSpanType = (spanData) => {
6532
+ const kind = spanKind(spanData);
6533
+ if (kind === "generation" || kind === "response" || kind === "transcription" || kind === "speech" || kind === "speech_group") return "LLM";
6534
+ if (kind === "function" || kind === "tool" || kind === "mcp_list_tools" || kind === "mcp_tools" || kind === "handoff") return "TOOL";
6535
+ return "DEFAULT";
6536
+ };
6537
+ const nameFromSpanData = (agent) => {
6538
+ if (agent == null) return "";
6539
+ if (typeof agent === "string") return agent;
6540
+ if (typeof agent === "object") {
6541
+ if (typeof agent.name === "string") return agent.name;
6542
+ }
6543
+ return "";
6544
+ };
6545
+ const getFirstNotNull = (d, ...keys) => {
6546
+ if (d == null) return;
6547
+ for (const key of keys) {
6548
+ const v = d[key];
6549
+ if (v !== void 0 && v !== null) return v;
6550
+ }
6551
+ };
6552
+ const modelAsDict = (obj) => {
6553
+ if (obj == null) return;
6554
+ if (typeof obj !== "object") return;
6555
+ if (Array.isArray(obj)) return;
6556
+ return obj;
6557
+ };
6558
+ const normalizeMessages = (data, role = "user") => {
6559
+ if (data == null) return [];
6560
+ if (typeof data === "string") return [{
6561
+ role,
6562
+ content: data
6563
+ }];
6564
+ if (Array.isArray(data)) {
6565
+ const messages = [];
6566
+ for (const item of data) if (item != null && typeof item === "object" && !Array.isArray(item)) messages.push(item);
6567
+ else messages.push({
6568
+ role,
6569
+ content: String(item)
6570
+ });
6571
+ return messages;
6572
+ }
6573
+ if (typeof data === "object") return [data];
6574
+ return [{
6575
+ role,
6576
+ content: String(data)
6577
+ }];
6578
+ };
6579
+ //#endregion
6580
+ //#region src/opentelemetry-lib/instrumentation/openai/utils.ts
6581
+ const INPUT_MESSAGES = "gen_ai.input.messages";
6582
+ const OUTPUT_MESSAGES = "gen_ai.output.messages";
6583
+ const TOOL_DEFINITIONS = "gen_ai.tool.definitions";
6584
+ const STRUCTURED_OUTPUT_SCHEMA = "gen_ai.request.structured_output_schema";
6585
+ const toJson = (value) => {
6586
+ if (value === void 0 || value === null) return void 0;
6587
+ return JSON.stringify(value);
6588
+ };
6589
+ /**
6590
+ * Base URL of the client behind a resource instance. openai >= 4 resources
6591
+ * hold the client in `_client`; the v3 `OpenAIApi` keeps `basePath` itself.
6592
+ */
6593
+ const getBaseUrl = (instance) => {
6594
+ const baseUrl = instance?._client?.baseURL ?? instance?.basePath ?? instance?.configuration?.basePath;
6595
+ return typeof baseUrl === "string" ? baseUrl : void 0;
6596
+ };
6597
+ const getVendorFromUrl = (baseUrl) => {
6598
+ if (!baseUrl) return "openai";
6599
+ if (baseUrl.includes("openai.azure.com")) return "Azure";
6600
+ if (baseUrl.includes("amazonaws.com") || baseUrl.includes("bedrock")) return "AWS";
6601
+ if (baseUrl.includes("googleapis.com") || baseUrl.includes("vertex")) return "Google";
6602
+ if (baseUrl.includes("openrouter.ai")) return "OpenRouter";
6603
+ return "openai";
6604
+ };
6605
+ /**
6606
+ * Bedrock model ids carry a vendor (`anthropic.claude-...`) and optionally a
6607
+ * cross-region prefix (`us.anthropic.claude-...`); keep only the model.
6608
+ */
6609
+ const crossRegionCheck = (model) => {
6610
+ if (!model.includes(".")) return model;
6611
+ const parts = model.split(".");
6612
+ if ([
6613
+ "us",
6614
+ "us-gov",
6615
+ "eu",
6616
+ "apac"
6617
+ ].includes(parts[0])) return parts.length > 2 ? parts.slice(2).join(".") : model;
6618
+ return parts.slice(1).join(".");
6619
+ };
6620
+ /**
6621
+ * Client attributes shared by every span: the vendor (from the base URL) as
6622
+ * `gen_ai.system`, the base URL itself and, for Azure, the API version.
6623
+ */
6624
+ const setClientAttributes = (span, instance) => {
6625
+ const baseUrl = getBaseUrl(instance);
6626
+ const vendor = getVendorFromUrl(baseUrl);
6627
+ safeSetAttribute$2(span, "gen_ai.system", vendor);
6628
+ safeSetAttribute$2(span, "gen_ai.request.base_url", baseUrl);
6629
+ const client = instance?._client;
6630
+ safeSetAttribute$2(span, "gen_ai.openai.api_version", client?.apiVersion ?? client?._options?.defaultQuery?.["api-version"]);
6631
+ return vendor;
6632
+ };
6633
+ const extractStructuredOutputSchema = (params) => {
6634
+ const responseFormat = params?.response_format;
6635
+ if (responseFormat?.type === "json_schema") return toJson(responseFormat.json_schema?.schema);
6636
+ };
6637
+ /**
6638
+ * Request attributes common to chat and legacy completions.
6639
+ */
6640
+ const setRequestAttributes$2 = (span, params, instance) => {
6641
+ const vendor = setClientAttributes(span, instance);
6642
+ let model = params?.model;
6643
+ if (vendor === "AWS" && typeof model === "string") model = crossRegionCheck(model);
6644
+ safeSetAttribute$2(span, "gen_ai.request.model", model);
6645
+ safeSetAttribute$2(span, "gen_ai.request.max_tokens", params?.max_tokens);
6646
+ safeSetAttribute$2(span, "gen_ai.request.temperature", params?.temperature);
6647
+ safeSetAttribute$2(span, "gen_ai.request.top_p", params?.top_p);
6648
+ safeSetAttribute$2(span, "gen_ai.request.frequency_penalty", params?.frequency_penalty);
6649
+ safeSetAttribute$2(span, "gen_ai.request.presence_penalty", params?.presence_penalty);
6650
+ safeSetAttribute$2(span, "llm.user", params?.user);
6651
+ span.setAttribute("llm.is_streaming", Boolean(params?.stream));
6652
+ safeSetAttribute$2(span, "gen_ai.request.reasoning_effort", params?.reasoning_effort);
6653
+ safeSetAttribute$2(span, "openai.request.service_tier", params?.service_tier);
6654
+ safeSetAttribute$2(span, STRUCTURED_OUTPUT_SCHEMA, extractStructuredOutputSchema(params));
6655
+ };
6656
+ const setChatPromptAttributes = (span, params) => {
6657
+ safeSetAttribute$2(span, INPUT_MESSAGES, toJson(params?.messages));
6658
+ safeSetAttribute$2(span, TOOL_DEFINITIONS, toJson(params?.functions ?? params?.tools));
6659
+ };
6660
+ const setCompletionPromptAttributes = (span, params) => {
6661
+ const prompt = params?.prompt;
6662
+ if (prompt !== void 0 && prompt !== null) safeSetAttribute$2(span, INPUT_MESSAGES, toJson((Array.isArray(prompt) ? prompt : [prompt]).map((content) => ({
6663
+ role: "user",
6664
+ content
6665
+ }))));
6666
+ safeSetAttribute$2(span, TOOL_DEFINITIONS, toJson(params?.functions));
6667
+ };
6668
+ const setEmbeddingsPromptAttributes = (span, params) => {
6669
+ const input = params?.input;
6670
+ if (input === void 0 || input === null) return;
6671
+ safeSetAttribute$2(span, INPUT_MESSAGES, toJson((Array.isArray(input) ? input : [input]).map((content) => ({ content }))));
6672
+ };
6673
+ /**
6674
+ * Response attributes for chat completions, legacy completions and
6675
+ * embeddings (and accumulated stream responses, which share the shape).
6676
+ */
6677
+ const setResponseAttributes$2 = (span, response) => {
6678
+ if (!response || typeof response !== "object") return;
6679
+ if (response.error) {
6680
+ safeSetAttribute$2(span, "gen_ai.prompt.prompt_error", toJson(response.error));
6681
+ return;
6682
+ }
6683
+ safeSetAttribute$2(span, "gen_ai.response.model", response.model);
6684
+ safeSetAttribute$2(span, "gen_ai.response.id", response.id);
6685
+ safeSetAttribute$2(span, "openai.response.system_fingerprint", response.system_fingerprint);
6686
+ safeSetAttribute$2(span, "gen_ai.prompt.prompt_filter_results", toJson(response.prompt_filter_results));
6687
+ safeSetAttribute$2(span, "openai.response.service_tier", response.service_tier);
6688
+ const usage = response.usage;
6689
+ if (!usage || typeof usage !== "object") return;
6690
+ span.setAttribute("llm.usage.total_tokens", usage.total_tokens ?? 0);
6691
+ span.setAttribute("gen_ai.usage.output_tokens", usage.completion_tokens ?? 0);
6692
+ span.setAttribute("gen_ai.usage.input_tokens", usage.prompt_tokens ?? 0);
6693
+ span.setAttribute("gen_ai.usage.cache_read_input_tokens", usage.prompt_tokens_details?.cached_tokens ?? 0);
6694
+ if (usage.completion_tokens_details) span.setAttribute("gen_ai.usage.reasoning_tokens", usage.completion_tokens_details.reasoning_tokens ?? 0);
6695
+ };
6696
+ const setChoicesAttributes = (span, response) => {
6697
+ if (Array.isArray(response?.choices)) safeSetAttribute$2(span, OUTPUT_MESSAGES, toJson(response.choices));
6698
+ };
6699
+ /**
6700
+ * Fold a chat completion chunk into the accumulated `ChatCompletion`.
6701
+ */
6702
+ const accumulateChatChunk = (complete, chunk) => {
6703
+ if (!chunk || typeof chunk !== "object") return;
6704
+ complete.id ??= chunk.id;
6705
+ complete.model ??= chunk.model;
6706
+ complete.created ??= chunk.created;
6707
+ complete.service_tier = chunk.service_tier ?? complete.service_tier;
6708
+ complete.system_fingerprint = chunk.system_fingerprint ?? complete.system_fingerprint;
6709
+ if (chunk.prompt_filter_results) complete.prompt_filter_results = chunk.prompt_filter_results;
6710
+ const usage = chunk.usage ?? chunk.choices?.[0]?.usage;
6711
+ if (usage) complete.usage = usage;
6712
+ for (const choice of chunk.choices ?? []) {
6713
+ const index = choice.index ?? 0;
6714
+ complete.choices[index] ??= {
6715
+ index,
6716
+ message: {
6717
+ role: "",
6718
+ content: ""
6719
+ }
6720
+ };
6721
+ const target = complete.choices[index];
6722
+ if (choice.finish_reason) target.finish_reason = choice.finish_reason;
6723
+ if (choice.content_filter_results) target.content_filter_results = choice.content_filter_results;
6724
+ const delta = choice.delta ?? {};
6725
+ if (delta.role) target.message.role = delta.role;
6726
+ if (delta.content) target.message.content += delta.content;
6727
+ if (delta.refusal) target.message.refusal = (target.message.refusal ?? "") + delta.refusal;
6728
+ if (delta.function_call) {
6729
+ target.message.function_call ??= {
6730
+ name: "",
6731
+ arguments: ""
6732
+ };
6733
+ target.message.function_call.name += delta.function_call.name ?? "";
6734
+ target.message.function_call.arguments += delta.function_call.arguments ?? "";
6735
+ }
6736
+ for (const toolCall of delta.tool_calls ?? []) {
6737
+ target.message.tool_calls ??= [];
6738
+ const toolIndex = toolCall.index ?? 0;
6739
+ target.message.tool_calls[toolIndex] ??= {
6740
+ id: "",
6741
+ type: "function",
6742
+ function: {
6743
+ name: "",
6744
+ arguments: ""
6745
+ }
6746
+ };
6747
+ const call = target.message.tool_calls[toolIndex];
6748
+ if (toolCall.id) call.id = toolCall.id;
6749
+ if (toolCall.function?.name) call.function.name = toolCall.function.name;
6750
+ call.function.arguments += toolCall.function?.arguments ?? "";
6751
+ }
6752
+ }
6753
+ };
6754
+ /**
6755
+ * Fold a legacy completion chunk into the accumulated `Completion`.
6756
+ */
6757
+ const accumulateCompletionChunk = (complete, chunk) => {
6758
+ if (!chunk || typeof chunk !== "object") return;
6759
+ complete.id ??= chunk.id;
6760
+ complete.model ??= chunk.model;
6761
+ complete.created ??= chunk.created;
6762
+ if (chunk.usage) complete.usage = chunk.usage;
6763
+ for (const choice of chunk.choices ?? []) {
6764
+ const index = choice.index ?? 0;
6765
+ complete.choices[index] ??= {
6766
+ index,
6767
+ text: ""
6768
+ };
6769
+ const target = complete.choices[index];
6770
+ target.text += choice.text ?? "";
6771
+ if (choice.finish_reason) target.finish_reason = choice.finish_reason;
6772
+ }
6773
+ };
6774
+ /**
6775
+ * `decisions.create` request attributes.
6776
+ */
6777
+ const setDecisionRequestAttributes = (span, params, instance, traceContent) => {
6778
+ setClientAttributes(span, instance);
6779
+ safeSetAttribute$2(span, "gen_ai.request.model", params?.model);
6780
+ safeSetAttribute$2(span, "llm.user", params?.safety_identifier);
6781
+ if (!traceContent) return;
6782
+ const input = params?.input;
6783
+ if (typeof input === "string") safeSetAttribute$2(span, INPUT_MESSAGES, toJson([{
6784
+ role: "user",
6785
+ content: input
6786
+ }]));
6787
+ else if (Array.isArray(input)) safeSetAttribute$2(span, INPUT_MESSAGES, toJson(input));
6788
+ if (Array.isArray(params?.questions)) safeSetAttribute$2(span, STRUCTURED_OUTPUT_SCHEMA, toJson(params.questions));
6789
+ };
6790
+ const setDecisionResponseAttributes = (span, response, traceContent) => {
6791
+ if (!response || typeof response !== "object") return;
6792
+ safeSetAttribute$2(span, "gen_ai.response.model", response.model);
6793
+ const usage = response.usage;
6794
+ if (usage && typeof usage === "object") {
6795
+ safeSetAttribute$2(span, "gen_ai.usage.input_tokens", usage.input_tokens);
6796
+ safeSetAttribute$2(span, "gen_ai.usage.output_tokens", usage.output_tokens);
6797
+ safeSetAttribute$2(span, "llm.usage.total_tokens", usage.total_tokens);
6798
+ safeSetAttribute$2(span, "gen_ai.usage.cache_read_input_tokens", usage.input_tokens_details?.cached_tokens);
6799
+ safeSetAttribute$2(span, "gen_ai.usage.cache_creation_input_tokens", usage.input_tokens_details?.cache_write_tokens);
6800
+ safeSetAttribute$2(span, "gen_ai.usage.reasoning_tokens", usage.output_tokens_details?.reasoning_tokens);
6801
+ }
6802
+ if (traceContent && Array.isArray(response.answers)) safeSetAttribute$2(span, OUTPUT_MESSAGES, toJson([{
6803
+ role: "assistant",
6804
+ content: toJson(response.answers)
6805
+ }]));
6806
+ };
6807
+ //#endregion
6808
+ //#region src/opentelemetry-lib/instrumentation/openai/responses.ts
6809
+ const RESPONSE_SPAN_NAME = "openai.response";
6810
+ const TERMINAL_STATUSES = /* @__PURE__ */ new Set([
6811
+ "completed",
6812
+ "incomplete",
6813
+ "failed",
6814
+ "cancelled"
6815
+ ]);
6816
+ const pendingResponses = /* @__PURE__ */ new Map();
6817
+ const recordedResponses = /* @__PURE__ */ new Set();
6818
+ const MAX_RECORDED_RESPONSES = 1e3;
6819
+ const markRecorded = (responseId) => {
6820
+ if (!responseId) return;
6821
+ recordedResponses.delete(responseId);
6822
+ recordedResponses.add(responseId);
6823
+ if (recordedResponses.size > MAX_RECORDED_RESPONSES) {
6824
+ const [oldest] = recordedResponses;
6825
+ recordedResponses.delete(oldest);
6826
+ }
6827
+ };
6828
+ const createStreamState = () => ({
6829
+ outputText: "",
6830
+ outputBlocks: {}
6831
+ });
6832
+ const getFunctionTools = (params) => Array.isArray(params?.tools) ? params.tools.filter((tool) => tool?.type === "function") : [];
6833
+ const outputBlocksOf = (response) => {
6834
+ const blocks = {};
6835
+ if (!Array.isArray(response?.output)) return blocks;
6836
+ response.output.forEach((block, index) => {
6837
+ blocks[block?.id ?? `output_${index}`] = block;
6838
+ });
6839
+ return blocks;
6840
+ };
6841
+ /**
6842
+ * Data for a call that produced no response to read from (a request error,
6843
+ * or a stream that ended before any snapshot), merged with anything stashed
6844
+ * under `params.response_id`.
6845
+ */
6846
+ const tracedDataFromRequest = (startTime, params) => {
6847
+ const responseId = params?.response_id ?? "";
6848
+ const existing = pendingResponses.get(responseId);
6849
+ const tools = getFunctionTools(params);
6850
+ return {
6851
+ startTime: existing?.startTime ?? startTime,
6852
+ responseId,
6853
+ input: params?.input ?? existing?.input,
6854
+ instructions: params?.instructions ?? existing?.instructions,
6855
+ tools: tools.length ? tools : existing?.tools,
6856
+ outputBlocks: { ...existing?.outputBlocks },
6857
+ outputText: existing?.outputText,
6858
+ usage: existing?.usage,
6859
+ requestModel: params?.model ?? existing?.requestModel,
6860
+ responseModel: existing?.responseModel,
6861
+ requestReasoningSummary: params?.reasoning?.summary ?? existing?.requestReasoningSummary,
6862
+ requestReasoningEffort: params?.reasoning?.effort ?? existing?.requestReasoningEffort,
6863
+ requestServiceTier: params?.service_tier ?? existing?.requestServiceTier
6864
+ };
6865
+ };
6866
+ /**
6867
+ * Merge a response into the data stashed under its id: request fields prefer
6868
+ * the stash (a `retrieve` carries no request body), response fields and
6869
+ * output blocks prefer the new response.
6870
+ */
6871
+ const tracedDataFromResponse = (startTime, response, params) => {
6872
+ const responseId = response?.id;
6873
+ if (!responseId) return void 0;
6874
+ const existing = pendingResponses.get(responseId);
6875
+ const tools = [...existing?.tools ?? [], ...getFunctionTools(params)];
6876
+ return {
6877
+ startTime: existing?.startTime ?? startTime,
6878
+ responseId,
6879
+ input: existing?.input ?? params?.input,
6880
+ instructions: existing?.instructions ?? params?.instructions,
6881
+ tools: tools.length ? tools : void 0,
6882
+ outputBlocks: {
6883
+ ...existing?.outputBlocks,
6884
+ ...outputBlocksOf(response)
6885
+ },
6886
+ outputText: response.output_text || existing?.outputText,
6887
+ usage: response.usage ?? existing?.usage,
6888
+ requestModel: existing?.requestModel ?? params?.model,
6889
+ responseModel: response.model ?? existing?.responseModel,
6890
+ requestReasoningSummary: existing?.requestReasoningSummary ?? params?.reasoning?.summary,
6891
+ requestReasoningEffort: existing?.requestReasoningEffort ?? params?.reasoning?.effort,
6892
+ requestServiceTier: existing?.requestServiceTier ?? params?.service_tier,
6893
+ responseServiceTier: response.service_tier ?? existing?.responseServiceTier
6894
+ };
6895
+ };
6896
+ const buildInputMessages = (data) => {
6897
+ const messages = [];
6898
+ if (typeof data.instructions === "string" && data.instructions) messages.push({
6899
+ role: "system",
6900
+ content: data.instructions
6901
+ });
6902
+ if (typeof data.input === "string") messages.push({
6903
+ role: "user",
6904
+ content: data.input
6905
+ });
6906
+ else if (Array.isArray(data.input)) for (const item of data.input) messages.push(item && typeof item === "object" && !("type" in item) ? {
6907
+ ...item,
6908
+ type: "message"
6909
+ } : item);
6910
+ return messages.length ? messages : void 0;
6911
+ };
6912
+ const buildOutputMessages = (data) => {
6913
+ const blocks = Object.values(data.outputBlocks).filter(Boolean);
6914
+ if (!blocks.length && data.outputText) return [{
6915
+ type: "message",
6916
+ role: "assistant",
6917
+ content: [{
6918
+ type: "output_text",
6919
+ text: data.outputText
6920
+ }]
6921
+ }];
6922
+ return blocks;
6923
+ };
6924
+ const setDataAttributes = (span, data, instance, traceContent) => {
6925
+ setClientAttributes(span, instance);
6926
+ safeSetAttribute$2(span, "gen_ai.request.model", data.requestModel);
6927
+ safeSetAttribute$2(span, "gen_ai.response.id", data.responseId);
6928
+ safeSetAttribute$2(span, "gen_ai.response.model", data.responseModel);
6929
+ const usage = data.usage;
6930
+ if (usage && typeof usage === "object") {
6931
+ safeSetAttribute$2(span, "gen_ai.usage.input_tokens", usage.input_tokens);
6932
+ safeSetAttribute$2(span, "gen_ai.usage.output_tokens", usage.output_tokens);
6933
+ safeSetAttribute$2(span, "llm.usage.total_tokens", usage.total_tokens);
6934
+ safeSetAttribute$2(span, "gen_ai.usage.cache_read_input_tokens", usage.input_tokens_details?.cached_tokens);
6935
+ span.setAttribute("gen_ai.usage.reasoning_tokens", usage.output_tokens_details?.reasoning_tokens ?? 0);
6936
+ }
6937
+ safeSetAttribute$2(span, "gen_ai.request.reasoning_summary", data.requestReasoningSummary);
6938
+ safeSetAttribute$2(span, "gen_ai.request.reasoning_effort", data.requestReasoningEffort);
6939
+ safeSetAttribute$2(span, "openai.request.service_tier", data.requestServiceTier);
6940
+ safeSetAttribute$2(span, "openai.response.service_tier", data.responseServiceTier);
6941
+ if (traceContent) {
6942
+ safeSetAttribute$2(span, INPUT_MESSAGES, toJson(buildInputMessages(data)));
6943
+ safeSetAttribute$2(span, OUTPUT_MESSAGES, toJson(buildOutputMessages(data)));
6944
+ safeSetAttribute$2(span, TOOL_DEFINITIONS, toJson(data.tools));
6945
+ }
6946
+ };
6947
+ const isDuplicate = (responseId, options) => Boolean(options.isRetrieve) && recordedResponses.has(responseId);
6948
+ const startResponseSpan = (data, options) => {
6949
+ const span = Laminar.startSpan({
6950
+ name: RESPONSE_SPAN_NAME,
6951
+ spanType: "LLM",
6952
+ startTime: data.startTime,
6953
+ context: options.parentContext
6954
+ });
6955
+ setDataAttributes(span, data, options.instance, options.traceContent);
6956
+ return span;
6957
+ };
6958
+ const markFailed = (span, message) => {
6959
+ span.recordException(new Error(message));
6960
+ span.setStatus({
6961
+ code: _opentelemetry_api.SpanStatusCode.ERROR,
6962
+ message
6963
+ });
6964
+ };
6965
+ const failureMessage = (response) => {
6966
+ switch (response?.status) {
6967
+ case "failed": return response.error?.message ?? "Response failed";
6968
+ case "cancelled": return "Response cancelled";
6969
+ default: return;
6970
+ }
6971
+ };
6972
+ /**
6973
+ * A `create` / `retrieve` that returned a response object. The span is
6974
+ * emitted once the response is final; until then (background mode) its
6975
+ * request data waits in the stash.
6976
+ */
6977
+ const processResponse = (startTime, response, params, options) => {
6978
+ const data = tracedDataFromResponse(startTime, response, params);
6979
+ if (!data) return;
6980
+ const status = response?.status;
6981
+ if (status && !TERMINAL_STATUSES.has(status)) {
6982
+ pendingResponses.set(data.responseId, data);
6983
+ return;
6984
+ }
6985
+ pendingResponses.delete(data.responseId);
6986
+ if (isDuplicate(data.responseId, options)) return;
6987
+ markRecorded(data.responseId);
6988
+ const span = startResponseSpan(data, options);
6989
+ const failure = failureMessage(response);
6990
+ if (failure !== void 0) markFailed(span, failure);
6991
+ else span.setStatus({ code: _opentelemetry_api.SpanStatusCode.OK });
6992
+ span.end();
6993
+ };
6994
+ /**
6995
+ * Start the span of a call that failed before returning a response; the
6996
+ * caller records the error and ends it.
6997
+ */
6998
+ const processRequestError = (startTime, params, options) => {
6999
+ const data = tracedDataFromRequest(startTime, params);
7000
+ pendingResponses.delete(data.responseId);
7001
+ return startResponseSpan(data, options);
7002
+ };
7003
+ /**
7004
+ * `cancel` of a background response we were tracking: emit its span.
7005
+ */
7006
+ const processCancel = (response, options) => {
7007
+ const responseId = response?.id;
7008
+ const existing = responseId ? pendingResponses.get(responseId) : void 0;
7009
+ if (!existing) return;
7010
+ pendingResponses.delete(responseId);
7011
+ markRecorded(responseId);
7012
+ const data = tracedDataFromResponse(existing.startTime, response, {}) ?? existing;
7013
+ const span = startResponseSpan(data, options);
7014
+ markFailed(span, "Response cancelled");
7015
+ span.end();
7016
+ };
7017
+ /**
7018
+ * Fold one `ResponseStreamEvent` into the stream state.
7019
+ */
7020
+ const processStreamEvent = (state, event) => {
7021
+ switch (event?.type) {
7022
+ case "response.output_text.delta":
7023
+ state.outputText += event.delta ?? "";
7024
+ break;
7025
+ case "response.output_item.done":
7026
+ if (event.item) state.outputBlocks[event.item.id ?? `output_${event.output_index}`] = event.item;
7027
+ break;
7028
+ case "error": state.errorMessage = event.message ?? "Response stream error";
7029
+ }
7030
+ if (event?.response && typeof event.response === "object") state.snapshot = event.response;
7031
+ };
7032
+ /**
7033
+ * Emit the span of a finished (or abandoned) stream. Returns the span so the
7034
+ * caller can record a thrown iteration error before ending it, or undefined
7035
+ * when no span is due: the stream re-read a response that already has one,
7036
+ * or it left a background response unfinished, which is stashed for the
7037
+ * `retrieve` / `cancel` that sees it finish.
7038
+ */
7039
+ const finishStream = (startTime, state, params, options) => {
7040
+ const snapshot = state.snapshot;
7041
+ if (isDuplicate(snapshot?.id ?? params?.response_id ?? "", options)) return;
7042
+ let data = snapshot && tracedDataFromResponse(startTime, snapshot, params) || tracedDataFromRequest(startTime, params);
7043
+ data = {
7044
+ ...data,
7045
+ outputBlocks: {
7046
+ ...state.outputBlocks,
7047
+ ...data.outputBlocks
7048
+ },
7049
+ outputText: data.outputText || state.outputText || void 0
7050
+ };
7051
+ if (snapshot && data.responseId) {
7052
+ if ((params?.background || options.isRetrieve) && !TERMINAL_STATUSES.has(snapshot.status) && state.errorMessage === void 0) {
7053
+ pendingResponses.set(data.responseId, data);
7054
+ return;
7055
+ }
7056
+ pendingResponses.delete(data.responseId);
7057
+ markRecorded(data.responseId);
7058
+ }
7059
+ const span = startResponseSpan(data, options);
7060
+ const failure = state.errorMessage ?? failureMessage(snapshot);
7061
+ if (failure !== void 0) markFailed(span, failure);
7062
+ else span.setStatus({ code: _opentelemetry_api.SpanStatusCode.OK });
7063
+ return span;
7064
+ };
7065
+ //#endregion
7066
+ //#region src/opentelemetry-lib/instrumentation/openai/index.ts
7067
+ const logger$16 = require_utils.initializeLogger();
7068
+ const PATCH_DATA_SYMBOL = Symbol("lmnr.openai.patchData");
7069
+ const hasOwnPatchData = (proto) => Object.getOwnPropertyDescriptor(proto, PATCH_DATA_SYMBOL) !== void 0;
7070
+ const markSpanError = (span, error) => {
7071
+ span.recordException(error);
7072
+ span.setAttribute("error.type", error?.constructor?.name ?? "Error");
7073
+ span.setStatus({ code: _opentelemetry_api.SpanStatusCode.ERROR });
7074
+ };
7075
+ /**
7076
+ * Attribute extraction must never break the user's call.
7077
+ */
7078
+ const safely = (fn) => {
7079
+ try {
7080
+ fn();
7081
+ } catch (error) {
7082
+ logger$16.debug(`Failed to set openai span attributes: ${String(error)}`);
7083
+ }
7084
+ };
7085
+ const isAsyncIterable$1 = (value) => value !== null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function";
7086
+ /**
7087
+ * Calls made by the OpenAI Agents SDK are already traced by its trace
7088
+ * processor, which sets this key around the model call.
7089
+ */
7090
+ const isDisabledByAgents = () => Boolean(LaminarContextManager.getContext().getValue(DISABLE_OPENAI_RESPONSES_INSTRUMENTATION_CONTEXT_KEY) ?? _opentelemetry_api.context.active().getValue(DISABLE_OPENAI_RESPONSES_INSTRUMENTATION_CONTEXT_KEY));
7091
+ const stripUndefined = (value) => {
7092
+ if (!value || typeof value !== "object") return value;
7093
+ return Object.fromEntries(Object.entries(value).filter(([, v]) => v !== void 0));
7094
+ };
7095
+ /**
7096
+ * Wrap the events of an SDK `Stream` as the caller iterates them. The stream
7097
+ * object itself is kept, so `tee()`, `toReadableStream()`, `controller` and
7098
+ * the SDK's stream helpers (`ChatCompletionStream`, `ResponseStream`) keep
7099
+ * working. `onDone` runs exactly once: on completion, on an iteration error,
7100
+ * or when the caller stops early.
7101
+ */
7102
+ const instrumentStream = (stream, onEvent, onDone) => {
7103
+ let done = false;
7104
+ const finish = (error) => {
7105
+ if (done) return;
7106
+ done = true;
7107
+ onDone(error);
7108
+ };
7109
+ const wrap = (makeIterator) => async function* () {
7110
+ const iterable = { [Symbol.asyncIterator]: makeIterator };
7111
+ try {
7112
+ for await (const event of iterable) {
7113
+ safely(() => onEvent(event));
7114
+ yield event;
7115
+ }
7116
+ } catch (error) {
7117
+ finish(error);
7118
+ throw error;
7119
+ } finally {
7120
+ finish();
7121
+ }
7122
+ };
7123
+ if (typeof stream.iterator === "function") {
7124
+ stream.iterator = wrap(stream.iterator);
7125
+ return;
7126
+ }
7127
+ stream[Symbol.asyncIterator] = wrap(stream[Symbol.asyncIterator].bind(stream));
7128
+ };
7129
+ /**
7130
+ * Hand the result of the original call to `succeed` / `fail`. An
7131
+ * `APIPromise` stays one, so the caller keeps `withResponse()` /
7132
+ * `asResponse()`.
7133
+ */
7134
+ const settle = (result, succeed, fail) => {
7135
+ if (typeof result?._thenUnwrap === "function") {
7136
+ const responsePromise = typeof result._responseProps === "function" ? result._responseProps() : result.responsePromise;
7137
+ if (typeof responsePromise?.then === "function") responsePromise.then(void 0, fail);
7138
+ return result._thenUnwrap(succeed);
7139
+ }
7140
+ if (typeof result?.then === "function") return result.then(succeed, (error) => {
7141
+ fail(error);
7142
+ throw error;
7143
+ });
7144
+ return succeed(result);
7145
+ };
7146
+ const setChatRequest = (span, params, instance, traceContent) => {
7147
+ setRequestAttributes$2(span, params, instance);
7148
+ if (traceContent) setChatPromptAttributes(span, params);
7149
+ };
7150
+ const setCompletionRequest = (span, params, instance, traceContent) => {
7151
+ setRequestAttributes$2(span, params, instance);
7152
+ if (traceContent) setCompletionPromptAttributes(span, params);
7153
+ };
7154
+ const setChoicesResponse = (span, response, traceContent) => {
7155
+ setResponseAttributes$2(span, response);
7156
+ if (traceContent && !response?.error) setChoicesAttributes(span, response);
7157
+ };
7158
+ const CHAT = {
7159
+ spanName: "openai.chat",
7160
+ skipForAgents: true,
7161
+ setRequest: setChatRequest,
7162
+ setResponse: setChoicesResponse,
7163
+ accumulate: accumulateChatChunk
7164
+ };
7165
+ const COMPLETION = {
7166
+ spanName: "openai.completion",
7167
+ setRequest: setCompletionRequest,
7168
+ setResponse: setChoicesResponse,
7169
+ accumulate: accumulateCompletionChunk
7170
+ };
7171
+ const EMBEDDINGS = {
7172
+ spanName: "openai.embeddings",
7173
+ setRequest: (span, params, instance, traceContent) => {
7174
+ setRequestAttributes$2(span, params, instance);
7175
+ if (traceContent) setEmbeddingsPromptAttributes(span, params);
7176
+ },
7177
+ setResponse: (span, response) => setResponseAttributes$2(span, response)
7178
+ };
7179
+ const DECISION = {
7180
+ spanName: "openai.decision",
7181
+ setRequest: setDecisionRequestAttributes,
7182
+ setResponse: setDecisionResponseAttributes
7183
+ };
7184
+ const unwrapAxiosBody = (result) => result?.data;
7185
+ const V3_CHAT = {
7186
+ ...CHAT,
7187
+ accumulate: void 0,
7188
+ unwrapBody: unwrapAxiosBody
7189
+ };
7190
+ const V3_COMPLETION = {
7191
+ ...COMPLETION,
7192
+ accumulate: void 0,
7193
+ unwrapBody: unwrapAxiosBody
7194
+ };
7195
+ const wrapMethod = (patchData, handler) => function(params, ...rest) {
7196
+ const { original } = patchData;
7197
+ if ((0, _opentelemetry_core.isTracingSuppressed)(_opentelemetry_api.context.active()) || handler.skipForAgents && isDisabledByAgents()) return original.call(this, params, ...rest);
7198
+ const traceContent = patchData.traceContent;
7199
+ const span = Laminar.startSpan({
7200
+ name: handler.spanName,
7201
+ spanType: "LLM"
7202
+ });
7203
+ safely(() => handler.setRequest(span, params, this, traceContent));
7204
+ let result;
7205
+ try {
7206
+ result = Laminar.withSpan(span, () => ({ value: original.call(this, params, ...rest) })).value;
7207
+ } catch (error) {
7208
+ markSpanError(span, error);
7209
+ span.end();
7210
+ throw error;
7211
+ }
7212
+ let ended = false;
7213
+ const fail = (error) => {
7214
+ if (ended) return;
7215
+ ended = true;
7216
+ markSpanError(span, error);
7217
+ span.end();
7218
+ };
7219
+ const succeed = (data) => {
7220
+ if (ended) return data;
7221
+ ended = true;
7222
+ const body = handler.unwrapBody ? handler.unwrapBody(data) : data;
7223
+ if (params?.stream) {
7224
+ const { accumulate } = handler;
7225
+ if (accumulate && isAsyncIterable$1(body)) {
7226
+ const complete = { choices: [] };
7227
+ instrumentStream(body, (chunk) => accumulate(complete, chunk), (error) => {
7228
+ safely(() => handler.setResponse(span, complete, traceContent));
7229
+ if (error !== void 0) markSpanError(span, error);
7230
+ else span.setStatus({ code: _opentelemetry_api.SpanStatusCode.OK });
7231
+ span.end();
7232
+ });
7233
+ return data;
7234
+ }
7235
+ } else safely(() => handler.setResponse(span, body, traceContent));
7236
+ span.setStatus({ code: _opentelemetry_api.SpanStatusCode.OK });
7237
+ span.end();
7238
+ return data;
7239
+ };
7240
+ return settle(result, succeed, fail);
7241
+ };
7242
+ const responsesParams = (kind, args) => {
7243
+ switch (kind) {
7244
+ case "create": return stripUndefined(args[0]) ?? {};
7245
+ case "retrieve": return {
7246
+ response_id: args[0],
7247
+ ...stripUndefined(args[1] ?? {})
7248
+ };
7249
+ case "cancel": return { response_id: args[0] };
5105
7250
  }
5106
7251
  };
5107
- const DISABLE_OPENAI_RESPONSES_INSTRUMENTATION_CONTEXT_KEY = (0, _opentelemetry_api.createContextKey)("LMNR_DISABLE_OPENAI_RESPONSES_INSTRUMENTATION");
5108
- const systemInstructionsStorage = new async_hooks.AsyncLocalStorage();
5109
- const getCurrentSystemInstructions = () => systemInstructionsStorage.getStore();
5110
- const runWithSystemInstructions = (value, fn) => systemInstructionsStorage.run(value, fn);
5111
- const wrapStreamWithSystemInstructions = (value, source) => ({ [Symbol.asyncIterator]() {
5112
- let iterator;
5113
- const getIterator = () => {
5114
- if (iterator === void 0) iterator = systemInstructionsStorage.run(value, () => source[Symbol.asyncIterator]());
5115
- return iterator;
7252
+ /**
7253
+ * `responses.create` / `retrieve` / `cancel`. Unlike the other APIs, the
7254
+ * span is built after the fact from the final response (see
7255
+ * `responses.ts`), so a background response spans from its `create` to the
7256
+ * `retrieve` / `cancel` that sees it finish.
7257
+ */
7258
+ const wrapResponsesMethod = (patchData, kind) => function(...args) {
7259
+ const { original } = patchData;
7260
+ if ((0, _opentelemetry_core.isTracingSuppressed)(_opentelemetry_api.context.active()) || isDisabledByAgents()) return original.apply(this, args);
7261
+ const startTime = (0, _opentelemetry_core.hrTime)();
7262
+ const params = responsesParams(kind, args);
7263
+ const options = {
7264
+ instance: this,
7265
+ traceContent: patchData.traceContent,
7266
+ parentContext: LaminarContextManager.getContext(),
7267
+ isRetrieve: kind === "retrieve"
5116
7268
  };
5117
- return {
5118
- next: (..._args) => systemInstructionsStorage.run(value, () => getIterator().next()),
5119
- return: (returnValue) => {
5120
- const it = getIterator();
5121
- return it.return ? systemInstructionsStorage.run(value, () => it.return(returnValue)) : Promise.resolve({
5122
- done: true,
5123
- value: returnValue
5124
- });
5125
- },
5126
- throw: (err) => {
5127
- const it = getIterator();
5128
- return it.throw ? systemInstructionsStorage.run(value, () => it.throw(err)) : Promise.reject(err);
5129
- }
7269
+ let ended = false;
7270
+ const fail = (error) => {
7271
+ if (ended || kind === "cancel") return;
7272
+ ended = true;
7273
+ safely(() => {
7274
+ const span = processRequestError(startTime, params, options);
7275
+ markSpanError(span, error);
7276
+ span.end();
7277
+ });
5130
7278
  };
5131
- } });
5132
- const spanKind = (spanData) => {
5133
- if (spanData == null) return "";
5134
- return typeof spanData.type === "string" ? spanData.type : "";
5135
- };
5136
- const spanName = (span, spanData) => {
5137
- const name = span?.name;
5138
- if (typeof name === "string" && name) return name;
5139
- const kind = spanKind(spanData);
5140
- if (kind) {
5141
- if (kind === "agent" || kind === "custom" || kind === "function" || kind === "tool") return nameFromSpanData(spanData) || `agents.${kind}`;
5142
- return `agents.${kind}`;
7279
+ const succeed = (data) => {
7280
+ if (ended) return data;
7281
+ ended = true;
7282
+ if (kind === "cancel") safely(() => processCancel(data, options));
7283
+ else if (isAsyncIterable$1(data)) {
7284
+ const state = createStreamState();
7285
+ instrumentStream(data, (event) => processStreamEvent(state, event), (error) => safely(() => {
7286
+ const span = finishStream(startTime, state, params, options);
7287
+ if (!span) return;
7288
+ if (error !== void 0) markSpanError(span, error);
7289
+ span.end();
7290
+ }));
7291
+ } else safely(() => processResponse(startTime, data, params, options));
7292
+ return data;
7293
+ };
7294
+ let result;
7295
+ try {
7296
+ result = original.apply(this, args);
7297
+ } catch (error) {
7298
+ fail(error);
7299
+ throw error;
5143
7300
  }
5144
- return "agents.span";
7301
+ return settle(result, succeed, fail);
5145
7302
  };
5146
- const mapSpanType = (spanData) => {
5147
- const kind = spanKind(spanData);
5148
- if (kind === "generation" || kind === "response" || kind === "transcription" || kind === "speech" || kind === "speech_group") return "LLM";
5149
- if (kind === "function" || kind === "tool" || kind === "mcp_list_tools" || kind === "mcp_tools" || kind === "handoff") return "TOOL";
5150
- return "DEFAULT";
7303
+ /**
7304
+ * Resolve the `OpenAI` client class from the module namespace, its default
7305
+ * export, or the class itself.
7306
+ */
7307
+ const resolveClientClass = (mod) => {
7308
+ for (const candidate of [
7309
+ mod?.OpenAI,
7310
+ mod?.default,
7311
+ mod
7312
+ ]) if (typeof candidate?.Chat?.Completions === "function") return candidate;
5151
7313
  };
5152
- const nameFromSpanData = (agent) => {
5153
- if (agent == null) return "";
5154
- if (typeof agent === "string") return agent;
5155
- if (typeof agent === "object") {
5156
- if (typeof agent.name === "string") return agent.name;
5157
- }
5158
- return "";
7314
+ /**
7315
+ * Resolve the openai v3 `OpenAIApi` class from the module namespace, its
7316
+ * default export, or the class itself.
7317
+ */
7318
+ const resolveV3ApiClass = (mod) => {
7319
+ for (const candidate of [
7320
+ mod?.OpenAIApi,
7321
+ mod?.default?.OpenAIApi,
7322
+ mod
7323
+ ]) if (typeof candidate?.prototype?.createChatCompletion === "function") return candidate;
5159
7324
  };
5160
- const getFirstNotNull = (d, ...keys) => {
5161
- if (d == null) return;
5162
- for (const key of keys) {
5163
- const v = d[key];
5164
- if (v !== void 0 && v !== null) return v;
7325
+ const handlerTarget = (proto, method, handler) => ({
7326
+ proto,
7327
+ method,
7328
+ wrap: (patchData) => wrapMethod(patchData, handler)
7329
+ });
7330
+ const responsesTarget = (proto, kind) => ({
7331
+ proto,
7332
+ method: kind,
7333
+ wrap: (patchData) => wrapResponsesMethod(patchData, kind)
7334
+ });
7335
+ /**
7336
+ * Everything to patch in the given module; prototypes are undefined where
7337
+ * the installed SDK version lacks the resource.
7338
+ */
7339
+ const patchTargets = (moduleExports) => {
7340
+ const client = resolveClientClass(moduleExports);
7341
+ if (client) {
7342
+ const responses = client.Responses?.prototype;
7343
+ return [
7344
+ handlerTarget(client.Chat?.Completions?.prototype, "create", CHAT),
7345
+ handlerTarget(client.Completions?.prototype, "create", COMPLETION),
7346
+ handlerTarget(client.Embeddings?.prototype, "create", EMBEDDINGS),
7347
+ handlerTarget(client.Decisions?.prototype, "create", DECISION),
7348
+ responsesTarget(responses, "create"),
7349
+ responsesTarget(responses, "retrieve"),
7350
+ responsesTarget(responses, "cancel")
7351
+ ];
5165
7352
  }
7353
+ const v3Api = resolveV3ApiClass(moduleExports)?.prototype;
7354
+ if (v3Api) return [handlerTarget(v3Api, "createChatCompletion", V3_CHAT), handlerTarget(v3Api, "createCompletion", V3_COMPLETION)];
7355
+ return [];
5166
7356
  };
5167
- const modelAsDict = (obj) => {
5168
- if (obj == null) return;
5169
- if (typeof obj !== "object") return;
5170
- if (Array.isArray(obj)) return;
5171
- return obj;
5172
- };
5173
- const normalizeMessages = (data, role = "user") => {
5174
- if (data == null) return [];
5175
- if (typeof data === "string") return [{
5176
- role,
5177
- content: data
5178
- }];
5179
- if (Array.isArray(data)) {
5180
- const messages = [];
5181
- for (const item of data) if (item != null && typeof item === "object" && !Array.isArray(item)) messages.push(item);
5182
- else messages.push({
5183
- role,
5184
- content: String(item)
7357
+ /**
7358
+ * Instruments the `openai` package:
7359
+ * - openai >= 4: `chat.completions.create`, `completions.create`,
7360
+ * `embeddings.create`, `decisions.create` and `responses.create` /
7361
+ * `retrieve` / `cancel`. `chat.completions.parse()` / `stream()` /
7362
+ * `runTools()` and `responses.parse()` / `stream()` delegate to `create`,
7363
+ * so they are traced through it without nesting a second span.
7364
+ * - openai v3: `OpenAIApi#createChatCompletion` / `createCompletion`.
7365
+ */
7366
+ var OpenAIInstrumentation = class extends _opentelemetry_instrumentation.InstrumentationBase {
7367
+ constructor(config) {
7368
+ super("@lmnr/openai-instrumentation", require_utils.version, { enabled: true });
7369
+ this.traceContent = config?.traceContent ?? true;
7370
+ }
7371
+ init() {
7372
+ return new _opentelemetry_instrumentation.InstrumentationNodeModuleDefinition("openai", [">=3.1.0"], this.patch.bind(this), this.unpatch.bind(this));
7373
+ }
7374
+ /**
7375
+ * Accepts the `openai` module namespace or the `OpenAI` class (the
7376
+ * module's default export). For openai v3, the module or its `OpenAIApi`
7377
+ * class.
7378
+ */
7379
+ manuallyInstrument(module) {
7380
+ if (!patchTargets(module).length) {
7381
+ _opentelemetry_api.diag.warn("Could not find the OpenAI client in openai manual instrumentation input. Pass the openai module.");
7382
+ return;
7383
+ }
7384
+ _opentelemetry_api.diag.debug("Manually instrumenting openai");
7385
+ this.patch(module);
7386
+ }
7387
+ patch(moduleExports) {
7388
+ _opentelemetry_api.diag.debug("Patching openai");
7389
+ for (const target of patchTargets(moduleExports)) this.patchMethod(target);
7390
+ return moduleExports;
7391
+ }
7392
+ unpatch(moduleExports) {
7393
+ _opentelemetry_api.diag.debug("Unpatching openai");
7394
+ for (const { proto, method } of patchTargets(moduleExports)) {
7395
+ if (!proto || !hasOwnPatchData(proto)) continue;
7396
+ const patchData = proto[PATCH_DATA_SYMBOL];
7397
+ if (!patchData[method]) continue;
7398
+ proto[method] = patchData[method].original;
7399
+ delete patchData[method];
7400
+ if (!Object.keys(patchData).length) delete proto[PATCH_DATA_SYMBOL];
7401
+ }
7402
+ }
7403
+ /**
7404
+ * Replace `proto[method]` with a traced wrapper. Re-patching an already
7405
+ * patched method only refreshes `traceContent`, so repeated
7406
+ * initialization never double-wraps.
7407
+ */
7408
+ patchMethod({ proto, method, wrap }) {
7409
+ if (!proto || typeof proto[method] !== "function") return;
7410
+ if (!hasOwnPatchData(proto)) Object.defineProperty(proto, PATCH_DATA_SYMBOL, {
7411
+ value: {},
7412
+ writable: true,
7413
+ configurable: true,
7414
+ enumerable: false
5185
7415
  });
5186
- return messages;
7416
+ const existing = proto[PATCH_DATA_SYMBOL][method];
7417
+ if (existing) {
7418
+ existing.traceContent = this.traceContent;
7419
+ return;
7420
+ }
7421
+ const patchData = {
7422
+ traceContent: this.traceContent,
7423
+ original: proto[method]
7424
+ };
7425
+ proto[PATCH_DATA_SYMBOL][method] = patchData;
7426
+ proto[method] = wrap(patchData);
5187
7427
  }
5188
- if (typeof data === "object") return [data];
5189
- return [{
5190
- role,
5191
- content: String(data)
5192
- }];
5193
7428
  };
5194
7429
  //#endregion
5195
7430
  //#region src/opentelemetry-lib/instrumentation/openai-agents/messages.ts
@@ -7223,14 +9458,10 @@ const getStagehandInstrumentation = (playwrightInstrumentation, client, sessionR
7223
9458
  return stagehandInstrumentation;
7224
9459
  };
7225
9460
  const initInstrumentations = (client, suppressContentTracing, sessionRecordingOptions) => {
7226
- const enrichTokens = false;
7227
9461
  const instrumentations = [];
7228
- instrumentations.push(new _traceloop_instrumentation_openai.OpenAIInstrumentation({
7229
- enrichTokens,
7230
- traceContent: !suppressContentTracing
7231
- }));
7232
- instrumentations.push(new _traceloop_instrumentation_anthropic.AnthropicInstrumentation({ traceContent: !suppressContentTracing }));
7233
- instrumentations.push(new _traceloop_instrumentation_cohere.CohereInstrumentation({ traceContent: !suppressContentTracing }));
9462
+ instrumentations.push(new OpenAIInstrumentation({ traceContent: !suppressContentTracing }));
9463
+ instrumentations.push(new AnthropicInstrumentation({ traceContent: !suppressContentTracing }));
9464
+ instrumentations.push(new CohereInstrumentation({ traceContent: !suppressContentTracing }));
7234
9465
  instrumentations.push(new _traceloop_instrumentation_bedrock.BedrockInstrumentation({ traceContent: !suppressContentTracing }));
7235
9466
  instrumentations.push(new _traceloop_instrumentation_pinecone.PineconeInstrumentation());
7236
9467
  instrumentations.push(new _traceloop_instrumentation_langchain.LangChainInstrumentation({ traceContent: !suppressContentTracing }));
@@ -7244,6 +9475,7 @@ const initInstrumentations = (client, suppressContentTracing, sessionRecordingOp
7244
9475
  instrumentations.push(new PuppeteerInstrumentation(client, sessionRecordingOptions));
7245
9476
  }
7246
9477
  instrumentations.push(new GoogleGenAiInstrumentation({ traceContent: !suppressContentTracing }));
9478
+ instrumentations.push(new GoogleAIPlatformInstrumentation({ traceContent: !suppressContentTracing }));
7247
9479
  instrumentations.push(new KernelInstrumentation());
7248
9480
  instrumentations.push(new ClaudeAgentSDKInstrumentation());
7249
9481
  instrumentations.push(new OpencodeInstrumentation());
@@ -7253,34 +9485,27 @@ const initInstrumentations = (client, suppressContentTracing, sessionRecordingOp
7253
9485
  return instrumentations;
7254
9486
  };
7255
9487
  const manuallyInitInstrumentations = (client, instrumentModules, suppressContentTracing, sessionRecordingOptions) => {
7256
- const enrichTokens = false;
7257
9488
  const instrumentations = [];
7258
9489
  let playwrightInstrumentation;
7259
9490
  if (instrumentModules?.OpenAI && instrumentModules?.openAI) throw new Error("`openAI` is deprecated, but both `OpenAI` and `openAI` are provided. Please use `OpenAI` only.");
7260
9491
  if (instrumentModules?.openAI) {
7261
- const openAIInstrumentation = new _traceloop_instrumentation_openai.OpenAIInstrumentation({
7262
- enrichTokens,
7263
- traceContent: !suppressContentTracing
7264
- });
9492
+ const openAIInstrumentation = new OpenAIInstrumentation({ traceContent: !suppressContentTracing });
7265
9493
  instrumentations.push(openAIInstrumentation);
7266
9494
  openAIInstrumentation.manuallyInstrument(instrumentModules.openAI);
7267
9495
  }
7268
9496
  if (instrumentModules?.OpenAI) {
7269
- const openAIInstrumentation = new _traceloop_instrumentation_openai.OpenAIInstrumentation({
7270
- enrichTokens,
7271
- traceContent: !suppressContentTracing
7272
- });
9497
+ const openAIInstrumentation = new OpenAIInstrumentation({ traceContent: !suppressContentTracing });
7273
9498
  instrumentations.push(openAIInstrumentation);
7274
9499
  openAIInstrumentation.manuallyInstrument(instrumentModules.OpenAI);
7275
9500
  }
7276
9501
  if (instrumentModules?.anthropic) {
7277
- const anthropicInstrumentation = new _traceloop_instrumentation_anthropic.AnthropicInstrumentation({ traceContent: !suppressContentTracing });
9502
+ const anthropicInstrumentation = new AnthropicInstrumentation({ traceContent: !suppressContentTracing });
7278
9503
  instrumentations.push(anthropicInstrumentation);
7279
9504
  anthropicInstrumentation.manuallyInstrument(instrumentModules.anthropic);
7280
9505
  }
7281
9506
  if (instrumentModules?.azureOpenAI) logger$7.warn("Azure OpenAI instrumentation is no longer supported. Not enabling any instrumentation.");
7282
9507
  if (instrumentModules?.cohere) {
7283
- const cohereInstrumentation = new _traceloop_instrumentation_cohere.CohereInstrumentation({ traceContent: !suppressContentTracing });
9508
+ const cohereInstrumentation = new CohereInstrumentation({ traceContent: !suppressContentTracing });
7284
9509
  instrumentations.push(cohereInstrumentation);
7285
9510
  cohereInstrumentation.manuallyInstrument(instrumentModules.cohere);
7286
9511
  }
@@ -7339,6 +9564,11 @@ const manuallyInitInstrumentations = (client, instrumentModules, suppressContent
7339
9564
  instrumentations.push(googleGenAiInstrumentation);
7340
9565
  googleGenAiInstrumentation.manuallyInstrument(instrumentModules.google_genai);
7341
9566
  }
9567
+ if (instrumentModules?.google_aiplatform) {
9568
+ const googleAIPlatformInstrumentation = new GoogleAIPlatformInstrumentation({ traceContent: !suppressContentTracing });
9569
+ instrumentations.push(googleAIPlatformInstrumentation);
9570
+ googleAIPlatformInstrumentation.manuallyInstrument(instrumentModules.google_aiplatform);
9571
+ }
7342
9572
  if (instrumentModules?.openrouter) {
7343
9573
  const openRouterInstrumentation = new OpenRouterInstrumentation({ traceContent: !suppressContentTracing });
7344
9574
  instrumentations.push(openRouterInstrumentation);
@@ -8015,17 +10245,6 @@ const withSessionMetadata = (metadata) => {
8015
10245
  [SESSION_METADATA_KEY]: sessionId
8016
10246
  };
8017
10247
  };
8018
- const getAverageScores = (results) => {
8019
- const perScoreValues = {};
8020
- for (const result of results) for (const key in result.scores) {
8021
- const score = result.scores[key];
8022
- if (perScoreValues[key] && score !== null) perScoreValues[key].push(score);
8023
- else perScoreValues[key] = score !== null ? [score] : [];
8024
- }
8025
- const averageScores = {};
8026
- for (const key in perScoreValues) averageScores[key] = perScoreValues[key].reduce((a, b) => a + b, 0) / perScoreValues[key].length;
8027
- return averageScores;
8028
- };
8029
10248
  /**
8030
10249
  * HumanEvaluator is a class to register a human evaluator.
8031
10250
  */
@@ -8070,7 +10289,7 @@ var Evaluation = class {
8070
10289
  this.concurrencyLimit = DEFAULT_CONCURRENCY;
8071
10290
  this.traceDisableBatch = false;
8072
10291
  this.traceExportBatchSize = MAX_EXPORT_BATCH_SIZE;
8073
- this.uploadPromises = [];
10292
+ this.uploadPromises = /* @__PURE__ */ new Set();
8074
10293
  if (Object.keys(evaluators).length === 0) throw new Error("No evaluators provided");
8075
10294
  const evaluatorNameRegex = /^[\w\s-]+$/;
8076
10295
  for (const key in evaluators) if (!evaluatorNameRegex.test(key)) throw new Error(`Invalid evaluator key: "${key}".Keys must only contain letters, digits, hyphens, underscores, or spaces.`);
@@ -8135,16 +10354,15 @@ var Evaluation = class {
8135
10354
  logger$3.warn(`Error getting dataset ${source.name}: ` + require_utils.errorMessage(error));
8136
10355
  }
8137
10356
  }
8138
- let resultDatapoints;
8139
10357
  try {
8140
10358
  const length = await this.getLength();
8141
10359
  const evaluation = await this.client.evals.init(this.name, this.groupName, withSessionMetadata(this.metadata));
8142
10360
  const url = getEvaluationUrl(evaluation.projectId, evaluation.id, this.progressReporter.baseUrl, this.frontendPort);
8143
10361
  process.stdout.write(`\nCheck results at ${url}\n`);
8144
10362
  this.progressReporter.start({ length });
8145
- resultDatapoints = await this.evaluateInBatches(evaluation.id);
8146
- const averageScores = getAverageScores(resultDatapoints);
8147
- if (this.uploadPromises.length > 0) await Promise.all(this.uploadPromises);
10363
+ const averageScores = await this.evaluateInBatches(evaluation.id);
10364
+ if (this.uploadPromises.size > 0) await Promise.all(this.uploadPromises);
10365
+ if (this.uploadError) throw this.uploadError.error;
8148
10366
  this.progressReporter.stop({
8149
10367
  averageScores,
8150
10368
  projectId: evaluation.projectId,
@@ -8182,24 +10400,42 @@ var Evaluation = class {
8182
10400
  });
8183
10401
  return LaminarContextManager.runWithIsolatedContext([entityContext], async () => {
8184
10402
  const semaphore = new require_utils.Semaphore(this.concurrencyLimit);
8185
- const tasks = [];
10403
+ const inFlight = /* @__PURE__ */ new Set();
10404
+ const scoreSums = {};
10405
+ const scoreCounts = {};
10406
+ let firstError;
8186
10407
  const evaluateTask = async (datapoint, index) => {
8187
10408
  try {
8188
10409
  const result = await this.evaluateDatapoint(evalId, datapoint, index);
10410
+ for (const [key, value] of Object.entries(result.scores ?? {})) {
10411
+ if (value === null) continue;
10412
+ scoreSums[key] = (scoreSums[key] ?? 0) + value;
10413
+ scoreCounts[key] = (scoreCounts[key] ?? 0) + 1;
10414
+ }
8189
10415
  this.progressReporter.update(1);
8190
- return [index, result];
10416
+ } catch (error) {
10417
+ firstError ??= { error };
8191
10418
  } finally {
8192
10419
  semaphore.release();
8193
10420
  }
8194
10421
  };
8195
- for (let i = 0; i < await this.getLength(); i++) {
10422
+ let index = 0;
10423
+ for await (const datapoint of this.data) {
8196
10424
  await semaphore.acquire();
8197
- const datapoint = Array.isArray(this.data) ? this.data[i] : await this.data.get(i);
8198
- tasks.push(evaluateTask(datapoint, i));
10425
+ const task = evaluateTask(datapoint, index++).finally(() => inFlight.delete(task));
10426
+ inFlight.add(task);
8199
10427
  }
8200
- return (await Promise.all(tasks)).sort((a, b) => a[0] - b[0]).map(([, result]) => result);
10428
+ await Promise.all(inFlight);
10429
+ if (firstError) throw firstError.error;
10430
+ return Object.fromEntries(Object.keys(scoreSums).map((key) => [key, scoreSums[key] / scoreCounts[key]]));
8201
10431
  });
8202
10432
  }
10433
+ trackUpload(upload) {
10434
+ const tracked = upload.then(() => void 0, (error) => {
10435
+ this.uploadError ??= { error };
10436
+ }).finally(() => this.uploadPromises.delete(tracked));
10437
+ this.uploadPromises.add(tracked);
10438
+ }
8203
10439
  async evaluateDatapoint(evalId, datapoint, index) {
8204
10440
  return observe({
8205
10441
  name: "evaluation",
@@ -8282,12 +10518,11 @@ var Evaluation = class {
8282
10518
  datapointId: datapoint.id,
8283
10519
  createdAt: datapoint.createdAt
8284
10520
  };
8285
- const uploadPromise = this.client.evals.saveDatapoints({
10521
+ this.trackUpload(this.client.evals.saveDatapoints({
8286
10522
  evalId,
8287
10523
  datapoints: [resultDatapoint],
8288
10524
  groupName: this.groupName
8289
- });
8290
- this.uploadPromises.push(uploadPromise);
10525
+ }));
8291
10526
  return resultDatapoint;
8292
10527
  });
8293
10528
  }
@@ -8334,165 +10569,10 @@ async function evaluate({ data, executor, evaluators, groupName, name, metadata,
8334
10569
  //#region src/integrations/eve.ts
8335
10570
  const logger$2 = require_utils.initializeLogger();
8336
10571
  const EVE_REPORTER_TRACER_NAME = "@lmnr-ai/lmnr/eve-reporter";
8337
- const EVE_CLIENT_MODULE = "eve/client";
8338
- const TRACEPARENT_HEADER$1 = "traceparent";
8339
- /** Same wire name the Temporal instrumentation uses (`temporal/consts.ts`). */
8340
- const LAMINAR_SPAN_CONTEXT_HEADER$1 = "x-lmnr-span-context";
8341
- /**
8342
- * Root span name for every propagated eval, and it never changes. eve calls
8343
- * `ClientSession.send` before any hook that knows which eval is in flight, and
8344
- * eve exposes no `onEvalStart`, so the id simply is not knowable here. Renaming
8345
- * the span later would invalidate the `lmnr.span.path` the processor already
8346
- * stamped on it and on every descendant, and would make the path we propagate
8347
- * to the agent stale. The eval id rides on `lmnr.eve.eval.id`, on the trace
8348
- * metadata, and on the datapoint instead.
8349
- */
8350
- const ROOT_SPAN_NAME = "eve eval";
8351
- const EXECUTOR_SPAN_NAME = "executor";
8352
- /** Prototypes already patched — `send` must never be wrapped twice. */
8353
- const patchedSendPrototypes = /* @__PURE__ */ new WeakSet();
8354
- /**
8355
- * Per-eve-client-session state. Keyed off the `ClientSession` instance rather
8356
- * than an AsyncLocalStorage frame or a "current eval" global: eve runs up to
8357
- * `maxConcurrency` evals at once, and each eval builds its own `ClientSession`
8358
- * (`EvalSessionManager` calls `client.session()` per `EvalSessionDriver`), so
8359
- * the instance is the only correct correlation key available inside `send`.
8360
- */
8361
- const traceByClientSession = /* @__PURE__ */ new WeakMap();
8362
- /** eve session id -> trace, read by `onEvalComplete` via `result.sessionId`. */
8363
- const traceByEveSessionId = /* @__PURE__ */ new Map();
8364
- /** Set by the running reporter's `onRunStart`; cleared by `onRunComplete`. */
8365
- let activeSessionTraceFactory = null;
8366
- /** Mirrors eve's own `normalizeSendTurnInput`, then merges the trace headers. */
8367
- const withTraceHeaders = (input, headers) => {
8368
- const payload = typeof input === "string" ? { message: input } : { ...input };
8369
- payload.headers = {
8370
- ...payload.headers ?? {},
8371
- ...headers
8372
- };
8373
- return payload;
8374
- };
8375
- const openSessionTrace = (clientSession) => {
8376
- try {
8377
- const existing = traceByClientSession.get(clientSession);
8378
- if (existing) return existing;
8379
- const minted = activeSessionTraceFactory?.();
8380
- if (minted) traceByClientSession.set(clientSession, minted);
8381
- return minted;
8382
- } catch (error) {
8383
- logger$2.warn(`Laminar eve reporter: failed to open a session trace: ` + require_utils.errorMessage(error));
8384
- return;
8385
- }
8386
- };
8387
- /**
8388
- * eve assigns the session id on the POST that `send` awaits, so the returned
8389
- * `MessageResponse` is the earliest place the runner can bind the eve session
8390
- * id to the trace it minted.
8391
- */
8392
- const recordEveSessionId = (response, sessionTrace) => {
8393
- const sessionId = response?.sessionId;
8394
- if (typeof sessionId !== "string" || sessionId.length === 0) return;
8395
- sessionTrace.sessionIds.add(sessionId);
8396
- traceByEveSessionId.set(sessionId, sessionTrace);
8397
- };
8398
- /**
8399
- * Build the propagation headers for the EXECUTOR span. Plain HTTP strings — eve
8400
- * forwards `SendTurnPayload.headers` verbatim to `fetch`.
8401
- *
8402
- * The Laminar context carries the full path. Laminar nests spans by
8403
- * `lmnr.span.ids_path`, not by OTel `parentSpanId`, so a receiver that adopts
8404
- * only the ids lands its spans as a second root on our trace. The path is what
8405
- * makes the agent's subtree render UNDER the executor. Both paths are constants
8406
- * here — neither the root nor the executor span is ever renamed.
8407
- */
8408
- const buildTraceHeaders = (rootSpan, executorSpan) => {
8409
- const spanContext = executorSpan.spanContext();
8410
- const laminarContext = {
8411
- traceId: require_utils.otelTraceIdToUUID(spanContext.traceId),
8412
- spanId: require_utils.otelSpanIdToUUID(spanContext.spanId),
8413
- isRemote: true,
8414
- spanPath: [ROOT_SPAN_NAME, EXECUTOR_SPAN_NAME],
8415
- spanIdsPath: [require_utils.otelSpanIdToUUID(rootSpan.spanContext().spanId), require_utils.otelSpanIdToUUID(spanContext.spanId)]
8416
- };
8417
- return {
8418
- [TRACEPARENT_HEADER$1]: `00-${spanContext.traceId}-${spanContext.spanId}-01`,
8419
- [LAMINAR_SPAN_CONTEXT_HEADER$1]: JSON.stringify(laminarContext)
8420
- };
8421
- };
8422
- /**
8423
- * Bind this session's ROOT span into the calling eval's async context, so work
8424
- * the eval does in the RUNNER process after `send` resolves lands on this trace
8425
- * instead of opening its own. The concrete case is `t.judge.autoevals.*`: eve
8426
- * runs the judge's model call in the runner, and Laminar's AI SDK integration
8427
- * parents it to `LaminarContextManager.getContext()`.
8428
- *
8429
- * The root — not a pre-opened judge span — is the binding target on purpose.
8430
- * An eval may record any number of judge assertions, and each one runs its own
8431
- * model call. Binding the root gives every judge its own child of the root; a
8432
- * single pre-opened parent would collect all of them under whichever judge
8433
- * happened to run first.
8434
- *
8435
- * `pushContext` uses `AsyncLocalStorage.enterWith`, so this MUST run
8436
- * synchronously before `send`'s first `await` — at that point we are still
8437
- * executing in the caller's async context, so the store we set is the one
8438
- * `test(t)` continues with. Each eval's `test(t)` runs in its own async chain,
8439
- * so concurrent evals never see each other's root span; do NOT replace this
8440
- * with the process-global context stack, which would cross-attribute.
8441
- *
8442
- * Judge spans reach Laminar only when the runner opts in — `Laminar.initialize()`
8443
- * plus a globally registered AI SDK telemetry integration. Without that the
8444
- * binding is inert, never wrong.
8445
- *
8446
- * Never popped: the store dies with the eval's async chain.
8447
- */
8448
- const bindEvalContext = (sessionTrace) => {
8449
- try {
8450
- LaminarContextManager.pushContext(_opentelemetry_api.trace.setSpan(_opentelemetry_api.ROOT_CONTEXT, sessionTrace.rootSpan));
8451
- } catch (error) {
8452
- logger$2.warn(`Laminar eve reporter: failed to bind the eval context: ` + require_utils.errorMessage(error));
8453
- }
8454
- };
8455
- /**
8456
- * Wrap `ClientSession.prototype.send` so every eve turn carries the trace
8457
- * context of a runner-minted Laminar span. Idempotent per prototype.
8458
- *
8459
- * @internal Exported for tests, which drive it with a stub class so the suite
8460
- * keeps no dependency on eve.
8461
- */
8462
- const patchEveClientSession = (sessionClass) => {
8463
- const prototype = sessionClass?.prototype;
8464
- const original = prototype?.send;
8465
- if (!prototype || typeof original !== "function") return false;
8466
- if (patchedSendPrototypes.has(prototype)) return true;
8467
- prototype.send = async function(input) {
8468
- const sessionTrace = openSessionTrace(this);
8469
- if (!sessionTrace) return original.call(this, input);
8470
- bindEvalContext(sessionTrace);
8471
- const response = await original.call(this, withTraceHeaders(input, sessionTrace.headers));
8472
- try {
8473
- recordEveSessionId(response, sessionTrace);
8474
- } catch (error) {
8475
- logger$2.warn(`Laminar eve reporter: failed to record the eve session id: ` + require_utils.errorMessage(error));
8476
- }
8477
- return response;
8478
- };
8479
- patchedSendPrototypes.add(prototype);
8480
- return true;
8481
- };
8482
- /**
8483
- * Load eve's `ClientSession` without depending on eve. Mirrors the guarded
8484
- * dynamic import in eve's own Braintrust reporter (`loadBraintrustSdk`), except
8485
- * a missing eve degrades instead of throwing — the reporter must keep working
8486
- * when it is registered outside an eve run.
8487
- */
8488
- const loadEveClientSession = async () => {
8489
- try {
8490
- const sessionClass = (await import(EVE_CLIENT_MODULE)).ClientSession;
8491
- return typeof sessionClass === "function" ? sessionClass : void 0;
8492
- } catch {
8493
- return;
8494
- }
8495
- };
10572
+ const OTEL_TRACE_ID_RE = /^[0-9a-f]{32}$/iu;
10573
+ const OTEL_SPAN_ID_RE = /^[0-9a-f]{16}$/iu;
10574
+ const ZERO_TRACE_ID = "0".repeat(32);
10575
+ const ZERO_SPAN_ID = "0".repeat(16);
8496
10576
  const didAssertionPass = (assertion) => {
8497
10577
  if (typeof assertion.passed === "boolean") return assertion.passed;
8498
10578
  if (typeof assertion.score === "number") {
@@ -8501,14 +10581,8 @@ const didAssertionPass = (assertion) => {
8501
10581
  }
8502
10582
  return true;
8503
10583
  };
8504
- /**
8505
- * Keep Laminar's top-level score columns stable across heterogeneous eve evals.
8506
- * Detailed assertion outcomes live in metadata; sparse per-assertion score keys
8507
- * make Laminar's eval UI look incomplete when different eval files assert
8508
- * different things.
8509
- */
8510
- const resultToScores = (result) => {
8511
- const assertions = result.assertions ?? [];
10584
+ /** Keep Laminar's score columns stable across heterogeneous eve evals. */
10585
+ const resultToScores = (result, assertions) => {
8512
10586
  const gateAssertions = assertions.filter((assertion) => assertion.severity === "gate");
8513
10587
  const thresholdedSoftAssertions = assertions.filter((assertion) => assertion.severity === "soft" && typeof assertion.threshold === "number");
8514
10588
  return {
@@ -8526,7 +10600,6 @@ const assertionsMetadata = (assertions) => assertions.map((assertion) => ({
8526
10600
  message: assertion.message,
8527
10601
  metadata: assertion.metadata
8528
10602
  }));
8529
- /** Surface failed assertions in metadata so a failing run is debuggable. */
8530
10603
  const failedAssertionsMetadata = (assertions) => {
8531
10604
  const failed = assertions.filter((assertion) => !didAssertionPass(assertion)).map((assertion) => ({
8532
10605
  name: assertion.name,
@@ -8534,79 +10607,62 @@ const failedAssertionsMetadata = (assertions) => {
8534
10607
  }));
8535
10608
  return failed.length > 0 ? { failedAssertions: failed } : {};
8536
10609
  };
8537
- const traceIdFromSpan = (span) => require_utils.otelTraceIdToUUID(span.spanContext().traceId);
10610
+ const validTraceContext = (context) => context != null && typeof context.traceId === "string" && OTEL_TRACE_ID_RE.test(context.traceId) && context.traceId !== ZERO_TRACE_ID && typeof context.spanId === "string" && OTEL_SPAN_ID_RE.test(context.spanId) && context.spanId !== ZERO_SPAN_ID && typeof context.traceFlags === "number" && Number.isInteger(context.traceFlags) && context.traceFlags >= 0 && context.traceFlags <= 255;
10611
+ const normalizeTraceContexts = (contexts) => Array.isArray(contexts) ? contexts.filter(validTraceContext) : [];
10612
+ const isSampledTraceContext = (context) => (context.traceFlags & 1) === 1;
10613
+ const selectTraceContext = (contexts) => contexts.find((context) => context.primary === true && isSampledTraceContext(context)) ?? contexts.find(isSampledTraceContext);
10614
+ const traceContextMetadata = (contexts) => contexts.map((context) => ({
10615
+ traceId: context.traceId,
10616
+ spanId: context.spanId,
10617
+ traceFlags: context.traceFlags,
10618
+ primary: context.primary,
10619
+ sessionId: context.sessionId
10620
+ }));
8538
10621
  /**
8539
- * A Laminar reporter for eve evals. Register it globally in `evals.config.ts`
8540
- * or per-eval via the `reporters` field — eve runs and grades each eval, then
8541
- * hands the graded result here, and this reporter ships it to Laminar as an
8542
- * evaluation run with one datapoint per eval.
10622
+ * Reports eve eval results to Laminar.
8543
10623
  *
8544
- * The datapoint's trace id is never looked up — the reporter OWNS the trace.
8545
- * `patchEveClientSession` wraps eve's `ClientSession.send` and mints the
8546
- * EVALUATION root + EXECUTOR child on the first turn of each session, so the
8547
- * runner already knows the trace id and pushes it to the agent as a
8548
- * `traceparent` header. The eve session id is only the in-process key that ties
8549
- * the send we instrumented to the graded result eve hands back later.
10624
+ * Eve 0.35+ gives reporters every native trace context observed during an eval.
10625
+ * The reporter links the datapoint to the first sampled primary trace (or the
10626
+ * first sampled trace when there is no sampled primary), records every valid
10627
+ * context in metadata, and adds
10628
+ * a small EVALUATION span to the selected native trace for the grade. When eve
10629
+ * reports no usable context, a reporter-owned fallback trace preserves the
10630
+ * result without pretending it contains agent work.
8550
10631
  *
8551
- * Two outcomes, recorded on `metadata.traceResolution`:
10632
+ * The agent must export its native OpenTelemetry spans to the same Laminar
10633
+ * project. In the eve agent, declare a destination like:
8552
10634
  *
8553
- * 1. `"propagated"` — the normal path, above. The agent joins the trace only
8554
- * when `agent/instrumentation.ts` sets `traceChannelRequests: true` and the
8555
- * agent process runs with `WORKFLOW_TRACE_MODE=continuous`.
8556
- * 2. `"reporter-fallback"` — no session trace was minted (propagation disabled,
8557
- * or eve produced no session id). The reporter opens its own EVALUATION span
8558
- * so the grade still lands somewhere debuggable; it holds no agent work.
8559
- *
8560
- * `t.judge.autoevals.*` model calls run in the RUNNER process, and they reach
8561
- * Laminar only when the runner registers an AI SDK telemetry integration. eve
8562
- * imports `generateText` inside its own bundle, so `wrapAISDK` cannot reach it —
8563
- * but AI SDK v7 reads registered integrations off `globalThis`, which does. One
8564
- * line in `evals.config.ts`:
8565
- *
8566
- * ```ts
8567
- * registerTelemetry(new LaminarAiSdkTelemetry());
8568
- * ```
8569
- *
8570
- * Judge spans and eve eval spans then share ONE tracer provider — whichever of
8571
- * the two initialized Laminar first (see {@link LaminarReporter.ensureTracing}).
8572
- * Each judge gets its own span under the eval's root — see
8573
- * {@link bindEvalContext}, and {@link LaminarReporter.flush} for how spans ship.
8574
- * Without that line the reporter still records every assertion's score as an
8575
- * EVALUATOR span; only the model call is missing.
8576
- *
8577
- * @example
8578
10635
  * ```ts
8579
- * import { defineEvalConfig } from "eve/evals";
8580
- * import { LaminarReporter } from "@lmnr-ai/lmnr";
10636
+ * import { LaminarSpanProcessor } from "@lmnr-ai/lmnr";
10637
+ * import { otelIntegration } from "eve/instrumentation/otel";
8581
10638
  *
8582
- * export default defineEvalConfig({
8583
- * reporters: [new LaminarReporter({ name: "weather-agent" })],
10639
+ * export default otelIntegration({
10640
+ * spanProcessors: [new LaminarSpanProcessor()],
8584
10641
  * });
8585
10642
  * ```
8586
10643
  */
8587
10644
  var LaminarReporter = class {
8588
10645
  constructor(options = {}) {
8589
10646
  this.evalsById = /* @__PURE__ */ new Map();
8590
- this.index = 0;
8591
- this.openSessionTraces = /* @__PURE__ */ new Set();
8592
- this.sessionTraceFactory = () => this.mintSessionTrace();
10647
+ this.evalIndexById = /* @__PURE__ */ new Map();
10648
+ this.nextFallbackIndex = 0;
8593
10649
  this.options = options;
8594
10650
  }
8595
10651
  async onRunStart(evaluations, target) {
8596
10652
  this.evalId = void 0;
8597
- this.evalsById = new Map(evaluations.filter((evaluation) => typeof evaluation.id === "string").map((evaluation) => [evaluation.id, evaluation]));
8598
- this.index = 0;
8599
- this.finishOpenSessionTraces();
10653
+ const identifiedEvaluations = evaluations.map((evaluation, index) => ({
10654
+ evaluation,
10655
+ index
10656
+ })).filter((item) => typeof item.evaluation.id === "string");
10657
+ this.evalsById = new Map(identifiedEvaluations.map(({ evaluation }) => [evaluation.id, evaluation]));
10658
+ this.evalIndexById = new Map(identifiedEvaluations.map(({ evaluation, index }) => [evaluation.id, index]));
10659
+ this.nextFallbackIndex = evaluations.length;
8600
10660
  try {
8601
10661
  this.client = this.options.client ?? new require_utils.LaminarClient({
8602
10662
  baseUrl: this.options.baseUrl,
8603
10663
  projectApiKey: this.options.projectApiKey
8604
10664
  });
8605
10665
  this.ensureTracing();
8606
- if (this.options.propagateTraceContext !== false) {
8607
- activeSessionTraceFactory = this.sessionTraceFactory;
8608
- patchEveClientSession(await loadEveClientSession());
8609
- }
8610
10666
  const evaluation = await this.client.evals.init(this.options.name, this.options.groupName, {
8611
10667
  ...this.options.metadata ?? {},
8612
10668
  source: "eve",
@@ -8619,26 +10675,25 @@ var LaminarReporter = class {
8619
10675
  process.stdout.write(`\nLaminar: check eve eval results at ${url}\n`);
8620
10676
  } catch (error) {
8621
10677
  logger$2.error(`Laminar eve reporter: failed to start run: ${require_utils.errorMessage(error)}`);
8622
- if (!this.evalId) {
8623
- this.client = void 0;
8624
- if (activeSessionTraceFactory === this.sessionTraceFactory) activeSessionTraceFactory = null;
8625
- }
10678
+ if (!this.evalId) this.client = void 0;
8626
10679
  }
8627
10680
  }
8628
- async onEvalComplete(result) {
10681
+ async onEvalComplete(result, context) {
8629
10682
  const client = this.client;
8630
10683
  const evalId = this.evalId;
8631
10684
  if (!client || !evalId) return;
8632
- const index = this.index++;
10685
+ const index = typeof result.id === "string" ? this.evalIndexById.get(result.id) ?? this.nextFallbackIndex++ : this.nextFallbackIndex++;
8633
10686
  const task = result.result ?? {};
8634
10687
  const derived = task.derived ?? {};
8635
- const assertions = result.assertions ?? [];
8636
- const evalDescription = (typeof result.id === "string" ? this.evalsById.get(result.id) : void 0)?.description;
8637
- const traceResolution = this.resolveDatapointTrace({
8638
- evalId: result.id ?? String(index),
10688
+ const assertions = Array.isArray(result.assertions) ? result.assertions.filter((assertion) => assertion != null && typeof assertion === "object") : [];
10689
+ const evalDefinition = typeof result.id === "string" ? this.evalsById.get(result.id) : void 0;
10690
+ const evalDescription = context?.evaluation?.description ?? evalDefinition?.description;
10691
+ const contexts = normalizeTraceContexts(context?.traceContexts ?? task.traceContexts ?? []);
10692
+ const gradeTrace = this.openGradeTrace({
10693
+ contexts,
8639
10694
  description: evalDescription,
8640
- verdict: result.verdict,
8641
- sessionId: task.sessionId
10695
+ evalId: result.id ?? String(index),
10696
+ verdict: result.verdict
8642
10697
  });
8643
10698
  try {
8644
10699
  const datapointId = await client.evals.createDatapoint({
@@ -8646,17 +10701,19 @@ var LaminarReporter = class {
8646
10701
  data: result.id ?? null,
8647
10702
  target: task.finalMessage ?? null,
8648
10703
  index,
8649
- traceId: traceResolution.traceId,
10704
+ traceId: gradeTrace.traceId,
8650
10705
  metadata: {
8651
10706
  name: result.id,
8652
10707
  verdict: result.verdict,
8653
10708
  status: task.status,
8654
10709
  description: evalDescription,
8655
10710
  sessionId: task.sessionId,
8656
- traceResolution: traceResolution.source,
10711
+ traceResolution: gradeTrace.source,
10712
+ selectedTraceContext: gradeTrace.selected ? traceContextMetadata([gradeTrace.selected])[0] : void 0,
10713
+ traceContexts: traceContextMetadata(gradeTrace.contexts),
8657
10714
  skipReason: result.skipReason,
8658
10715
  error: result.error,
8659
- toolCalls: (derived.toolCalls ?? []).map((call) => call.name).filter((name) => typeof name === "string"),
10716
+ toolCalls: (Array.isArray(derived.toolCalls) ? derived.toolCalls : []).map((call) => call?.name).filter((name) => typeof name === "string"),
8660
10717
  toolCallCount: derived.toolCallCount,
8661
10718
  parked: derived.parked,
8662
10719
  failureCode: derived.failureCode,
@@ -8665,44 +10722,30 @@ var LaminarReporter = class {
8665
10722
  ...failedAssertionsMetadata(assertions)
8666
10723
  }
8667
10724
  });
8668
- const executorOutput = task.output ?? task.finalMessage ?? null;
8669
10725
  await client.evals.updateDatapoint({
8670
10726
  evalId,
8671
10727
  datapointId,
8672
- scores: resultToScores(result),
8673
- executorOutput
10728
+ scores: resultToScores(result, assertions),
10729
+ executorOutput: task.output ?? task.finalMessage ?? null
8674
10730
  });
8675
10731
  } catch (error) {
8676
- if (traceResolution.source === "reporter-fallback") traceResolution.span.recordException(error);
10732
+ gradeTrace.span.recordException(error);
8677
10733
  logger$2.error(`Laminar eve reporter: failed to report eval "${result.id ?? index}": ${require_utils.errorMessage(error)}`);
8678
10734
  } finally {
8679
- if (traceResolution.source === "reporter-fallback") traceResolution.span.end();
8680
- if (traceResolution.source === "propagated") this.finishSessionTrace(traceResolution.sessionTrace, {
8681
- evalId: result.id,
8682
- description: evalDescription,
8683
- verdict: result.verdict,
8684
- status: task.status,
10735
+ this.finishGradeTrace(gradeTrace, {
10736
+ assertions,
8685
10737
  output: task.output ?? task.finalMessage ?? null,
8686
- assertions
10738
+ status: task.status
8687
10739
  });
8688
10740
  await this.flush();
8689
10741
  }
8690
10742
  }
8691
- async onRunComplete() {
8692
- this.finishOpenSessionTraces();
8693
- if (activeSessionTraceFactory === this.sessionTraceFactory) activeSessionTraceFactory = null;
10743
+ async onRunComplete(_summary) {
8694
10744
  await this.flush();
8695
10745
  this.evalId = void 0;
8696
10746
  this.evalsById.clear();
10747
+ this.evalIndexById.clear();
8697
10748
  }
8698
- /**
8699
- * Point the process's Laminar tracing at this reporter's project, unless
8700
- * something already initialized it. Mirrors `LaminarAiSdkTelemetry`, which
8701
- * initializes the same way for judge spans — so eve eval spans and judge
8702
- * spans share ONE tracer provider however the run was set up. Without this,
8703
- * `getTracer()` returns a noop whenever nobody registered the AI SDK
8704
- * integration, and every eve span would be dropped silently.
8705
- */
8706
10749
  ensureTracing() {
8707
10750
  if (Laminar.initialized()) {
8708
10751
  const ourKey = this.client?.apiKey ?? this.options.projectApiKey;
@@ -8718,140 +10761,79 @@ var LaminarReporter = class {
8718
10761
  disableBatch: true
8719
10762
  });
8720
10763
  }
8721
- /**
8722
- * Flush the process's Laminar pipeline — eve eval spans AND judge spans, which
8723
- * now share one provider. eve ends `eve eval` with `process.exit()` (skipping
8724
- * `beforeExit`), so these calls are the only points at which spans ship.
8725
- * Never `shutdown()`: the pipeline may belong to the host, not to us.
8726
- */
8727
10764
  async flush() {
8728
10765
  try {
8729
10766
  await Laminar.flush();
8730
10767
  } catch (error) {
8731
- logger$2.warn(`Laminar eve reporter: failed to flush spans: ` + require_utils.errorMessage(error));
10768
+ logger$2.warn(`Laminar eve reporter: failed to flush spans: ${require_utils.errorMessage(error)}`);
8732
10769
  }
8733
10770
  }
8734
- /**
8735
- * Open the eval's Laminar spans for one eve client session: an EVALUATION
8736
- * root plus the EXECUTOR child the agent's turn is parented to. Called from
8737
- * the patched `send`, so it must never throw into the user's eval.
8738
- */
8739
- mintSessionTrace() {
10771
+ openGradeTrace({ contexts, description, evalId, verdict }) {
10772
+ const selected = selectTraceContext(contexts);
8740
10773
  const tracer = getTracer();
8741
- const rootSpan = tracer.startSpan(ROOT_SPAN_NAME, { attributes: {
8742
- [require_utils.SPAN_TYPE]: "EVALUATION",
8743
- [require_utils.TRACE_TYPE]: "EVALUATION",
8744
- "lmnr.eve.reporter": EVE_REPORTER_TRACER_NAME
8745
- } }, _opentelemetry_api.ROOT_CONTEXT);
8746
- const executorSpan = tracer.startSpan(EXECUTOR_SPAN_NAME, { attributes: {
8747
- [require_utils.SPAN_TYPE]: "EXECUTOR",
8748
- [require_utils.TRACE_TYPE]: "EVALUATION"
8749
- } }, _opentelemetry_api.trace.setSpan(_opentelemetry_api.ROOT_CONTEXT, rootSpan));
8750
- const sessionTrace = {
8751
- traceId: require_utils.otelTraceIdToUUID(rootSpan.spanContext().traceId),
8752
- rootSpan,
8753
- executorSpan,
8754
- tracer,
8755
- headers: buildTraceHeaders(rootSpan, executorSpan),
8756
- sessionIds: /* @__PURE__ */ new Set(),
8757
- ended: false
8758
- };
8759
- this.openSessionTraces.add(sessionTrace);
8760
- return sessionTrace;
8761
- }
8762
- /** Grade, close and release one session trace. Idempotent. */
8763
- finishSessionTrace(sessionTrace, grade) {
8764
- if (sessionTrace.ended) return;
8765
- sessionTrace.ended = true;
8766
- this.openSessionTraces.delete(sessionTrace);
8767
- for (const sessionId of sessionTrace.sessionIds) traceByEveSessionId.delete(sessionId);
8768
- try {
8769
- sessionTrace.rootSpan.setAttributes({
8770
- "lmnr.eve.eval.id": grade.evalId ?? "",
8771
- "lmnr.eve.eval.verdict": grade.verdict ?? "",
8772
- "lmnr.eve.eval.status": grade.status ?? "",
8773
- [require_utils.SPAN_INPUT]: JSON.stringify({
8774
- evalId: grade.evalId,
8775
- description: grade.description
8776
- }),
8777
- [require_utils.SPAN_OUTPUT]: JSON.stringify(grade.output ?? null),
8778
- ...require_utils.metadataToAttributes({
8779
- source: "eve",
8780
- eveEvalId: grade.evalId ?? "",
8781
- eveEvalDescription: grade.description ?? "",
8782
- eveEvalVerdict: grade.verdict ?? "",
8783
- eveSessionId: [...sessionTrace.sessionIds].join(",")
8784
- })
8785
- });
8786
- sessionTrace.executorSpan.setAttribute(require_utils.SPAN_OUTPUT, JSON.stringify(grade.output ?? null));
8787
- this.recordEvaluatorSpans(sessionTrace, grade.assertions ?? []);
8788
- sessionTrace.executorSpan.end();
8789
- sessionTrace.rootSpan.end();
8790
- } catch (error) {
8791
- logger$2.warn(`Laminar eve reporter: failed to finish the session trace: ` + require_utils.errorMessage(error));
8792
- }
8793
- }
8794
- /**
8795
- * One EVALUATOR span per eve assertion, judge or not. They are created at
8796
- * grade time (the assertions only exist then) as short children of the
8797
- * still-open root. No explicit parent path is needed: the root keeps the name
8798
- * it was minted with, so the processor's cached path for it is still correct.
8799
- */
8800
- recordEvaluatorSpans(sessionTrace, assertions) {
8801
- const rootContext = _opentelemetry_api.trace.setSpan(_opentelemetry_api.ROOT_CONTEXT, sessionTrace.rootSpan);
8802
- for (const assertion of assertions) {
8803
- const name = assertion.name ?? "assertion";
8804
- const output = JSON.stringify({
8805
- score: assertion.score ?? null,
8806
- passed: didAssertionPass(assertion),
8807
- severity: assertion.severity,
8808
- threshold: assertion.threshold,
8809
- message: assertion.message
8810
- });
8811
- sessionTrace.tracer.startSpan(name, { attributes: {
8812
- [require_utils.SPAN_TYPE]: "EVALUATOR",
8813
- [require_utils.TRACE_TYPE]: "EVALUATION",
8814
- [require_utils.SPAN_OUTPUT]: output
8815
- } }, rootContext).end();
8816
- }
8817
- }
8818
- finishOpenSessionTraces() {
8819
- for (const sessionTrace of [...this.openSessionTraces]) this.finishSessionTrace(sessionTrace, {});
8820
- }
8821
- /**
8822
- * Resolve the trace this datapoint links to. There is no lookup: either
8823
- * `patchEveClientSession` already minted the session's trace (and we know its
8824
- * id), or we open a reporter-owned EVALUATION span to hold the grade.
8825
- */
8826
- resolveDatapointTrace({ evalId, description, verdict, sessionId }) {
8827
- const sessionTrace = sessionId ? traceByEveSessionId.get(sessionId) : void 0;
8828
- if (sessionTrace) return {
8829
- traceId: sessionTrace.traceId,
8830
- source: "propagated",
8831
- sessionTrace
8832
- };
8833
- const span = getTracer().startSpan(`eve eval ${evalId}`, { attributes: {
10774
+ const parentContext = selected ? _opentelemetry_api.trace.setSpanContext(_opentelemetry_api.ROOT_CONTEXT, this.toSpanContext(selected)) : _opentelemetry_api.ROOT_CONTEXT;
10775
+ const source = selected ? "eve-native" : "reporter-fallback";
10776
+ const span = tracer.startSpan(`eve eval ${evalId}`, { attributes: {
8834
10777
  [require_utils.SPAN_TYPE]: "EVALUATION",
8835
10778
  [require_utils.TRACE_TYPE]: "EVALUATION",
8836
10779
  "lmnr.eve.reporter": EVE_REPORTER_TRACER_NAME,
8837
10780
  "lmnr.eve.eval.id": evalId,
8838
10781
  "lmnr.eve.eval.verdict": verdict ?? "",
8839
- ...sessionId ? { "lmnr.eve.session.id": sessionId } : {},
8840
- "lmnr.eve.trace_resolution": "reporter-fallback",
10782
+ "lmnr.eve.trace_resolution": source,
8841
10783
  ...require_utils.metadataToAttributes({
8842
10784
  source: "eve",
8843
10785
  eveEvalId: evalId,
8844
10786
  eveEvalDescription: description ?? "",
8845
10787
  eveEvalVerdict: verdict ?? "",
8846
- eveSessionId: sessionId ?? ""
10788
+ eveSessionId: selected?.sessionId ?? "",
10789
+ eveTraceCount: contexts.length
10790
+ }),
10791
+ [require_utils.SPAN_INPUT]: JSON.stringify({
10792
+ evalId,
10793
+ description
8847
10794
  })
8848
- } }, _opentelemetry_api.ROOT_CONTEXT);
10795
+ } }, parentContext);
10796
+ return {
10797
+ traceId: require_utils.otelTraceIdToUUID(span.spanContext().traceId),
10798
+ source,
10799
+ span,
10800
+ tracer,
10801
+ selected,
10802
+ contexts
10803
+ };
10804
+ }
10805
+ toSpanContext(context) {
8849
10806
  return {
8850
- traceId: traceIdFromSpan(span),
8851
- source: "reporter-fallback",
8852
- span
10807
+ traceId: context.traceId.toLowerCase(),
10808
+ spanId: context.spanId.toLowerCase(),
10809
+ traceFlags: context.traceFlags,
10810
+ isRemote: true
8853
10811
  };
8854
10812
  }
10813
+ finishGradeTrace(gradeTrace, grade) {
10814
+ try {
10815
+ gradeTrace.span.setAttributes({
10816
+ "lmnr.eve.eval.status": grade.status ?? "",
10817
+ [require_utils.SPAN_OUTPUT]: JSON.stringify(grade.output ?? null)
10818
+ });
10819
+ const parentContext = _opentelemetry_api.trace.setSpan(_opentelemetry_api.ROOT_CONTEXT, gradeTrace.span);
10820
+ for (const assertion of grade.assertions) gradeTrace.tracer.startSpan(assertion.name ?? "assertion", { attributes: {
10821
+ [require_utils.SPAN_TYPE]: "EVALUATOR",
10822
+ [require_utils.TRACE_TYPE]: "EVALUATION",
10823
+ [require_utils.SPAN_OUTPUT]: JSON.stringify({
10824
+ score: assertion.score ?? null,
10825
+ passed: didAssertionPass(assertion),
10826
+ severity: assertion.severity,
10827
+ threshold: assertion.threshold,
10828
+ message: assertion.message
10829
+ })
10830
+ } }, parentContext).end();
10831
+ } catch (error) {
10832
+ logger$2.warn(`Laminar eve reporter: failed to finish the grade trace: ${require_utils.errorMessage(error)}`);
10833
+ } finally {
10834
+ gradeTrace.span.end();
10835
+ }
10836
+ }
8855
10837
  };
8856
10838
  //#endregion
8857
10839
  //#region src/debug/hash.ts