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