@lmnr-ai/lmnr 0.8.43 → 0.8.44
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/cli.cjs +2 -2
- package/dist/cli.d.cts +1 -1
- package/dist/cli.d.mts +1 -1
- package/dist/cli.mjs +2 -2
- package/dist/{consts-DV6_Ea-8.cjs → consts-9rSS0oeR.cjs} +2 -2
- package/dist/consts-9rSS0oeR.cjs.map +1 -0
- package/dist/{consts-3AfXaMBI.mjs → consts-CTTu3jhI.mjs} +2 -2
- package/dist/consts-CTTu3jhI.mjs.map +1 -0
- package/dist/{dist-Cwlsdtmn.cjs → dist-BtB31bk1.cjs} +25 -6
- package/dist/dist-BtB31bk1.cjs.map +1 -0
- package/dist/{dist-OcTWlPdQ.mjs → dist-Cjres0a5.mjs} +25 -6
- package/dist/dist-Cjres0a5.mjs.map +1 -0
- package/dist/{evaluations-CVOnF42k.d.mts → evaluations-CVo0ms_r.d.mts} +17 -3
- package/dist/{evaluations-CZcMEvqZ.d.cts → evaluations-RbBZb5yl.d.cts} +17 -3
- package/dist/{file-utils-BLJXFs0L.mjs → file-utils-1olUHMKC.mjs} +2 -2
- package/dist/{file-utils-BLJXFs0L.mjs.map → file-utils-1olUHMKC.mjs.map} +1 -1
- package/dist/{file-utils-C5DKc9p7.cjs → file-utils-CMO5MuV9.cjs} +2 -2
- package/dist/{file-utils-C5DKc9p7.cjs.map → file-utils-CMO5MuV9.cjs.map} +1 -1
- package/dist/index.cjs +706 -175
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +246 -3
- package/dist/index.d.mts +246 -3
- package/dist/index.mjs +706 -176
- package/dist/index.mjs.map +1 -1
- package/dist/opentelemetry-lib/instrumentation/temporal/workflow-interceptors.cjs +1 -1
- package/dist/opentelemetry-lib/instrumentation/temporal/workflow-interceptors.mjs +1 -1
- package/package.json +3 -3
- package/dist/consts-3AfXaMBI.mjs.map +0 -1
- package/dist/consts-DV6_Ea-8.cjs.map +0 -1
- package/dist/dist-Cwlsdtmn.cjs.map +0 -1
- package/dist/dist-OcTWlPdQ.mjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_rolldown_runtime = require("./rolldown-runtime-CVvi-lCc.cjs");
|
|
3
|
-
const require_dist = require("./dist-
|
|
4
|
-
const require_consts = require("./consts-
|
|
3
|
+
const require_dist = require("./dist-BtB31bk1.cjs");
|
|
4
|
+
const require_consts = require("./consts-9rSS0oeR.cjs");
|
|
5
5
|
let _opentelemetry_api = require("@opentelemetry/api");
|
|
6
6
|
let _opentelemetry_context_async_hooks = require("@opentelemetry/context-async-hooks");
|
|
7
7
|
let _opentelemetry_instrumentation = require("@opentelemetry/instrumentation");
|
|
@@ -183,7 +183,7 @@ var LaminarDataset = class extends EvaluationDataset {
|
|
|
183
183
|
*/
|
|
184
184
|
async push(paths, recursive = false) {
|
|
185
185
|
if (!this.client) throw new Error("Client not set");
|
|
186
|
-
const { loadFromPaths } = await Promise.resolve().then(() => require("./file-utils-
|
|
186
|
+
const { loadFromPaths } = await Promise.resolve().then(() => require("./file-utils-CMO5MuV9.cjs")).then((n) => n.file_utils_exports);
|
|
187
187
|
const data = await loadFromPaths(Array.isArray(paths) ? paths : [paths], recursive);
|
|
188
188
|
if (data.length === 0) {
|
|
189
189
|
console.warn("No data to push. Skipping");
|
|
@@ -199,7 +199,7 @@ var LaminarDataset = class extends EvaluationDataset {
|
|
|
199
199
|
};
|
|
200
200
|
//#endregion
|
|
201
201
|
//#region src/opentelemetry-lib/tracing/compat.ts
|
|
202
|
-
const logger$
|
|
202
|
+
const logger$25 = require_dist.initializeLogger();
|
|
203
203
|
const makeSpanOtelV2Compatible = (span) => {
|
|
204
204
|
const spanAny = span;
|
|
205
205
|
if (spanAny.instrumentationScope && !spanAny.instrumentationLibrary) Object.assign(span, { instrumentationLibrary: spanAny.instrumentationScope });
|
|
@@ -245,7 +245,7 @@ const createResource = (attributes) => {
|
|
|
245
245
|
if (resources.Resource) return new resources.Resource(attributes);
|
|
246
246
|
throw new Error("Unable to create Resource: neither v1 nor v2 API found");
|
|
247
247
|
} catch {
|
|
248
|
-
logger$
|
|
248
|
+
logger$25.debug("Laminar failed to @opentelemetry/resources, continuing without it");
|
|
249
249
|
return;
|
|
250
250
|
}
|
|
251
251
|
};
|
|
@@ -430,7 +430,7 @@ const consumeResponse = async (response) => {
|
|
|
430
430
|
};
|
|
431
431
|
//#endregion
|
|
432
432
|
//#region src/opentelemetry-lib/tracing/stream-utils.ts
|
|
433
|
-
const logger$
|
|
433
|
+
const logger$24 = require_dist.initializeLogger();
|
|
434
434
|
const pendingStreamProcessing = /* @__PURE__ */ new Set();
|
|
435
435
|
/**
|
|
436
436
|
* Wait for all pending stream processing to complete with a timeout
|
|
@@ -438,7 +438,7 @@ const pendingStreamProcessing = /* @__PURE__ */ new Set();
|
|
|
438
438
|
*/
|
|
439
439
|
const waitForPendingStreams = async (timeoutMs = 5e3) => {
|
|
440
440
|
if (pendingStreamProcessing.size === 0) return;
|
|
441
|
-
logger$
|
|
441
|
+
logger$24.debug(`Waiting for ${pendingStreamProcessing.size} pending stream(s)`);
|
|
442
442
|
const initialCount = pendingStreamProcessing.size;
|
|
443
443
|
const pendingPromises = Array.from(pendingStreamProcessing);
|
|
444
444
|
let timedOut = false;
|
|
@@ -449,7 +449,7 @@ const waitForPendingStreams = async (timeoutMs = 5e3) => {
|
|
|
449
449
|
}, timeoutMs);
|
|
450
450
|
});
|
|
451
451
|
await Promise.race([Promise.allSettled(pendingPromises), timeoutPromise]);
|
|
452
|
-
if (timedOut && pendingStreamProcessing.size > 0) logger$
|
|
452
|
+
if (timedOut && pendingStreamProcessing.size > 0) logger$24.warn(`Timeout waiting for ${pendingStreamProcessing.size} pending stream(s) after ${timeoutMs}ms (started with ${initialCount})`);
|
|
453
453
|
};
|
|
454
454
|
/**
|
|
455
455
|
* Track a background promise and ensure cleanup
|
|
@@ -465,34 +465,34 @@ const trackStreamProcessing = (task) => {
|
|
|
465
465
|
* while passing through the original result to the caller
|
|
466
466
|
*/
|
|
467
467
|
const handleStreamResult = (originalResult, streamInfo, span, ignoreOutput, serialize) => {
|
|
468
|
-
logger$
|
|
468
|
+
logger$24.debug(`Handling stream result of type: ${streamInfo.type}`);
|
|
469
469
|
if (streamInfo.type === "aisdk-result") {
|
|
470
470
|
trackStreamProcessing(async () => {
|
|
471
|
-
logger$
|
|
471
|
+
logger$24.debug("Starting background processing for AI SDK result");
|
|
472
472
|
let partialOutput = {};
|
|
473
473
|
try {
|
|
474
474
|
partialOutput = await consumeAISDKResult(streamInfo.result);
|
|
475
475
|
if (shouldSendTraces() && !ignoreOutput) try {
|
|
476
476
|
span.setAttribute(require_dist.SPAN_OUTPUT, serialize(partialOutput));
|
|
477
477
|
} catch (error) {
|
|
478
|
-
logger$
|
|
478
|
+
logger$24.warn("Failed to serialize AI SDK stream output: " + require_dist.errorMessage(error));
|
|
479
479
|
}
|
|
480
480
|
} catch (error) {
|
|
481
481
|
if (Object.keys(partialOutput).length > 0 && shouldSendTraces() && !ignoreOutput) try {
|
|
482
482
|
span.setAttribute(require_dist.SPAN_OUTPUT, serialize(partialOutput));
|
|
483
483
|
} catch (serError) {
|
|
484
|
-
logger$
|
|
484
|
+
logger$24.warn("Failed to serialize partial AI SDK output: " + require_dist.errorMessage(serError));
|
|
485
485
|
}
|
|
486
486
|
span.recordException(error);
|
|
487
487
|
} finally {
|
|
488
|
-
logger$
|
|
488
|
+
logger$24.debug("Ending span for AI SDK result");
|
|
489
489
|
span.end();
|
|
490
490
|
}
|
|
491
491
|
});
|
|
492
492
|
return originalResult;
|
|
493
493
|
}
|
|
494
494
|
if (streamInfo.type === "readable-stream") {
|
|
495
|
-
logger$
|
|
495
|
+
logger$24.debug("Setting up background processing for ReadableStream");
|
|
496
496
|
const { stream, dataPromise } = consumeAndTeeReadableStream(streamInfo.stream);
|
|
497
497
|
trackStreamProcessing(async () => {
|
|
498
498
|
try {
|
|
@@ -504,18 +504,18 @@ const handleStreamResult = (originalResult, streamInfo, span, ignoreOutput, seri
|
|
|
504
504
|
};
|
|
505
505
|
span.setAttribute(require_dist.SPAN_OUTPUT, serialize(output));
|
|
506
506
|
} catch (serError) {
|
|
507
|
-
logger$
|
|
507
|
+
logger$24.warn("Failed to serialize stream output: " + require_dist.errorMessage(serError));
|
|
508
508
|
}
|
|
509
509
|
if (error) span.recordException(error);
|
|
510
510
|
} finally {
|
|
511
|
-
logger$
|
|
511
|
+
logger$24.debug("Ending span for ReadableStream");
|
|
512
512
|
span.end();
|
|
513
513
|
}
|
|
514
514
|
});
|
|
515
515
|
return stream;
|
|
516
516
|
}
|
|
517
517
|
if (streamInfo.type === "async-iterable") {
|
|
518
|
-
logger$
|
|
518
|
+
logger$24.debug("Setting up background processing for AsyncIterable");
|
|
519
519
|
const { iterable, dataPromise } = consumeAndTeeAsyncIterable(streamInfo.iterable);
|
|
520
520
|
trackStreamProcessing(async () => {
|
|
521
521
|
try {
|
|
@@ -527,18 +527,18 @@ const handleStreamResult = (originalResult, streamInfo, span, ignoreOutput, seri
|
|
|
527
527
|
};
|
|
528
528
|
span.setAttribute(require_dist.SPAN_OUTPUT, serialize(output));
|
|
529
529
|
} catch (serError) {
|
|
530
|
-
logger$
|
|
530
|
+
logger$24.warn("Failed to serialize async iterable output: " + require_dist.errorMessage(serError));
|
|
531
531
|
}
|
|
532
532
|
if (error) span.recordException(error);
|
|
533
533
|
} finally {
|
|
534
|
-
logger$
|
|
534
|
+
logger$24.debug("Ending span for AsyncIterable");
|
|
535
535
|
span.end();
|
|
536
536
|
}
|
|
537
537
|
});
|
|
538
538
|
return iterable;
|
|
539
539
|
}
|
|
540
540
|
if (streamInfo.type === "response") {
|
|
541
|
-
logger$
|
|
541
|
+
logger$24.debug("Setting up background processing for Response");
|
|
542
542
|
const originalResponse = streamInfo.response;
|
|
543
543
|
if (!originalResponse.body) {
|
|
544
544
|
span.end();
|
|
@@ -560,19 +560,19 @@ const handleStreamResult = (originalResult, streamInfo, span, ignoreOutput, seri
|
|
|
560
560
|
};
|
|
561
561
|
span.setAttribute(require_dist.SPAN_OUTPUT, serialize(output));
|
|
562
562
|
} catch (serError) {
|
|
563
|
-
logger$
|
|
563
|
+
logger$24.warn("Failed to serialize response output: " + require_dist.errorMessage(serError));
|
|
564
564
|
}
|
|
565
565
|
if (error) span.recordException(error);
|
|
566
566
|
} catch (err) {
|
|
567
567
|
span.recordException(err);
|
|
568
568
|
} finally {
|
|
569
|
-
logger$
|
|
569
|
+
logger$24.debug("Ending span for Response");
|
|
570
570
|
span.end();
|
|
571
571
|
}
|
|
572
572
|
});
|
|
573
573
|
return newResponse;
|
|
574
574
|
}
|
|
575
|
-
logger$
|
|
575
|
+
logger$24.warn("Stream type not handled, ending span immediately");
|
|
576
576
|
span.end();
|
|
577
577
|
return originalResult;
|
|
578
578
|
};
|
|
@@ -650,7 +650,7 @@ const writeDebugSessionFile = (file, dir = process.cwd()) => {
|
|
|
650
650
|
* contract. This file is part of the cross-language parity surface — keep its
|
|
651
651
|
* logic line-comparable with the Python `config.py`.
|
|
652
652
|
*/
|
|
653
|
-
const logger$
|
|
653
|
+
const logger$23 = require_dist.initializeLogger();
|
|
654
654
|
const TRUTHY = new Set([
|
|
655
655
|
"true",
|
|
656
656
|
"1",
|
|
@@ -686,7 +686,7 @@ const parseCacheUntil = (value) => {
|
|
|
686
686
|
if (value === void 0 || value === "") return null;
|
|
687
687
|
const spanId = normalizeSpanId(value);
|
|
688
688
|
if (spanId !== null) return spanId;
|
|
689
|
-
logger$
|
|
689
|
+
logger$23.warn(`LMNR_DEBUG_CACHE_UNTIL=${JSON.stringify(value)} is not a span id; ignoring`);
|
|
690
690
|
return null;
|
|
691
691
|
};
|
|
692
692
|
/**
|
|
@@ -1037,7 +1037,7 @@ const resetDebugRuntime = () => {
|
|
|
1037
1037
|
};
|
|
1038
1038
|
//#endregion
|
|
1039
1039
|
//#region src/opentelemetry-lib/tracing/span.ts
|
|
1040
|
-
const logger$
|
|
1040
|
+
const logger$22 = require_dist.initializeLogger();
|
|
1041
1041
|
/**
|
|
1042
1042
|
* Build the debug block to propagate, or undefined when debug mode is off.
|
|
1043
1043
|
*
|
|
@@ -1187,7 +1187,7 @@ var LaminarSpan = class LaminarSpan {
|
|
|
1187
1187
|
} catch {}
|
|
1188
1188
|
metadata[key.replace(`${require_dist.ASSOCIATION_PROPERTIES}.metadata.`, "")] = value;
|
|
1189
1189
|
}
|
|
1190
|
-
} else logger$
|
|
1190
|
+
} else logger$22.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.");
|
|
1191
1191
|
return {
|
|
1192
1192
|
spanId: require_dist.otelSpanIdToUUID(this._span.spanContext().spanId),
|
|
1193
1193
|
traceId: require_dist.otelTraceIdToUUID(this._span.spanContext().traceId),
|
|
@@ -1214,14 +1214,14 @@ var LaminarSpan = class LaminarSpan {
|
|
|
1214
1214
|
}
|
|
1215
1215
|
get tags() {
|
|
1216
1216
|
if (!this._span.attributes) {
|
|
1217
|
-
logger$
|
|
1217
|
+
logger$22.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.");
|
|
1218
1218
|
return [];
|
|
1219
1219
|
}
|
|
1220
1220
|
return this._span.attributes[`lmnr.association.properties.tags`] ?? [];
|
|
1221
1221
|
}
|
|
1222
1222
|
get laminarAssociationProperties() {
|
|
1223
1223
|
if (!this._span.attributes) {
|
|
1224
|
-
logger$
|
|
1224
|
+
logger$22.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.");
|
|
1225
1225
|
return {};
|
|
1226
1226
|
}
|
|
1227
1227
|
try {
|
|
@@ -1417,7 +1417,7 @@ var LaminarContextManager = class {
|
|
|
1417
1417
|
};
|
|
1418
1418
|
//#endregion
|
|
1419
1419
|
//#region src/opentelemetry-lib/instrumentation/claude-agent-sdk/proxy.ts
|
|
1420
|
-
const logger$
|
|
1420
|
+
const logger$21 = require_dist.initializeLogger();
|
|
1421
1421
|
const DEFAULT_ANTHROPIC_BASE_URL = "https://api.anthropic.com";
|
|
1422
1422
|
const DEFAULT_CC_PROXY_PORT = 45667;
|
|
1423
1423
|
const CC_PROXY_PORT_ATTEMPTS = 50;
|
|
@@ -1669,7 +1669,7 @@ const resolveTargetUrlFromEnv = (envDict, fallback = DEFAULT_ANTHROPIC_BASE_URL,
|
|
|
1669
1669
|
if (foundryBaseUrl) return foundryBaseUrl.replace(/\/$/, "");
|
|
1670
1670
|
const foundryResource = getEnvValue(FOUNDRY_RESOURCE_ENV);
|
|
1671
1671
|
if (foundryResource) return `https://${foundryResource}.services.ai.azure.com/anthropic`;
|
|
1672
|
-
logger$
|
|
1672
|
+
logger$21.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.`);
|
|
1673
1673
|
return null;
|
|
1674
1674
|
}
|
|
1675
1675
|
if (isTruthyEnv(getEnvValue(BEDROCK_USE_ENV))) {
|
|
@@ -1678,7 +1678,7 @@ const resolveTargetUrlFromEnv = (envDict, fallback = DEFAULT_ANTHROPIC_BASE_URL,
|
|
|
1678
1678
|
let region = getEnvValue(BEDROCK_AWS_REGION_ENV);
|
|
1679
1679
|
if (!region) region = getRegionFromAwsConfig(getEnvValue("AWS_PROFILE") || "default") ?? void 0;
|
|
1680
1680
|
if (region) return `https://bedrock-runtime.${region}.amazonaws.com`;
|
|
1681
|
-
logger$
|
|
1681
|
+
logger$21.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.`);
|
|
1682
1682
|
return null;
|
|
1683
1683
|
}
|
|
1684
1684
|
if (isTruthyEnv(getEnvValue(VERTEX_USE_ENV))) {
|
|
@@ -1761,11 +1761,11 @@ const waitForPort = (port, timeoutMs = 5e3) => new Promise((resolve) => {
|
|
|
1761
1761
|
const registerGlobalProxyShutdown = () => {
|
|
1762
1762
|
if (!globalShutdownRegistered) {
|
|
1763
1763
|
process.on("exit", () => {
|
|
1764
|
-
logger$
|
|
1764
|
+
logger$21.debug("process.on(\"exit\") called - stopping all active proxies");
|
|
1765
1765
|
for (const proxyServer of activeProxyServers) try {
|
|
1766
1766
|
proxyServer.stopServer();
|
|
1767
1767
|
} catch (e) {
|
|
1768
|
-
logger$
|
|
1768
|
+
logger$21.debug(`Failed to stop proxy: ${require_dist.errorMessage(e)}`);
|
|
1769
1769
|
}
|
|
1770
1770
|
activeProxyServers.clear();
|
|
1771
1771
|
});
|
|
@@ -1780,28 +1780,28 @@ const createProxyInstance = async ({ env, cwd, settingSources, settings, targetU
|
|
|
1780
1780
|
try {
|
|
1781
1781
|
const port = await findAvailablePort(DEFAULT_CC_PROXY_PORT, CC_PROXY_PORT_ATTEMPTS);
|
|
1782
1782
|
if (port === null) {
|
|
1783
|
-
logger$
|
|
1783
|
+
logger$21.warn("Unable to allocate port for cc-proxy.");
|
|
1784
1784
|
return null;
|
|
1785
1785
|
}
|
|
1786
1786
|
const targetUrl = resolvedTargetUrl ?? resolveTargetUrlFromEnv(env, void 0, cwd, settingSources, settings);
|
|
1787
1787
|
if (!targetUrl) {
|
|
1788
|
-
logger$
|
|
1788
|
+
logger$21.warn("Unable to resolve target URL for cc-proxy (provider misconfigured).");
|
|
1789
1789
|
return null;
|
|
1790
1790
|
}
|
|
1791
|
-
logger$
|
|
1791
|
+
logger$21.debug(`Creating proxy instance on port ${port} targeting: ${targetUrl}`);
|
|
1792
1792
|
try {
|
|
1793
1793
|
const { ProxyServer } = require("@lmnr-ai/claude-code-proxy");
|
|
1794
1794
|
const proxyServer = new ProxyServer(port);
|
|
1795
1795
|
proxyServer.runServer(targetUrl);
|
|
1796
1796
|
if (!await waitForPort(port)) {
|
|
1797
|
-
logger$
|
|
1797
|
+
logger$21.warn(`cc-proxy failed to start on port ${port}`);
|
|
1798
1798
|
proxyServer.stopServer();
|
|
1799
1799
|
return null;
|
|
1800
1800
|
}
|
|
1801
1801
|
const proxyBaseUrl = `http://127.0.0.1:${port}`;
|
|
1802
1802
|
activeProxyServers.add(proxyServer);
|
|
1803
1803
|
registerGlobalProxyShutdown();
|
|
1804
|
-
logger$
|
|
1804
|
+
logger$21.info(`Started claude proxy server on: ${proxyBaseUrl}`);
|
|
1805
1805
|
return {
|
|
1806
1806
|
server: proxyServer,
|
|
1807
1807
|
baseUrl: proxyBaseUrl,
|
|
@@ -1809,11 +1809,11 @@ const createProxyInstance = async ({ env, cwd, settingSources, settings, targetU
|
|
|
1809
1809
|
targetUrl
|
|
1810
1810
|
};
|
|
1811
1811
|
} catch (e) {
|
|
1812
|
-
logger$
|
|
1812
|
+
logger$21.warn(`Unable to start cc-proxy: ${require_dist.errorMessage(e)}`);
|
|
1813
1813
|
return null;
|
|
1814
1814
|
}
|
|
1815
1815
|
} catch (e) {
|
|
1816
|
-
logger$
|
|
1816
|
+
logger$21.warn(`Failed to create proxy instance: ${require_dist.errorMessage(e)}`);
|
|
1817
1817
|
return null;
|
|
1818
1818
|
}
|
|
1819
1819
|
};
|
|
@@ -1823,11 +1823,11 @@ const createProxyInstance = async ({ env, cwd, settingSources, settings, targetU
|
|
|
1823
1823
|
const stopProxyInstance = (instance) => {
|
|
1824
1824
|
if (!instance) return;
|
|
1825
1825
|
try {
|
|
1826
|
-
logger$
|
|
1826
|
+
logger$21.debug(`Stopping proxy instance on port ${instance.port}`);
|
|
1827
1827
|
instance.server.stopServer();
|
|
1828
1828
|
activeProxyServers.delete(instance.server);
|
|
1829
1829
|
} catch (e) {
|
|
1830
|
-
logger$
|
|
1830
|
+
logger$21.debug(`Failed to stop proxy instance: ${require_dist.errorMessage(e)}`);
|
|
1831
1831
|
}
|
|
1832
1832
|
};
|
|
1833
1833
|
/**
|
|
@@ -1835,11 +1835,11 @@ const stopProxyInstance = (instance) => {
|
|
|
1835
1835
|
* Used during shutdown to ensure cleanup
|
|
1836
1836
|
*/
|
|
1837
1837
|
const forceReleaseProxy = () => {
|
|
1838
|
-
logger$
|
|
1838
|
+
logger$21.debug(`Force stopping all ${activeProxyServers.size} active proxy servers`);
|
|
1839
1839
|
for (const proxyServer of activeProxyServers) try {
|
|
1840
1840
|
proxyServer.stopServer();
|
|
1841
1841
|
} catch (e) {
|
|
1842
|
-
logger$
|
|
1842
|
+
logger$21.debug(`Failed to stop proxy: ${require_dist.errorMessage(e)}`);
|
|
1843
1843
|
}
|
|
1844
1844
|
activeProxyServers.clear();
|
|
1845
1845
|
};
|
|
@@ -1889,14 +1889,14 @@ const setTraceToProxyInstance = async (instance) => {
|
|
|
1889
1889
|
spanPath: payload.span_path,
|
|
1890
1890
|
laminarUrl: payload.laminar_url
|
|
1891
1891
|
});
|
|
1892
|
-
logger$
|
|
1892
|
+
logger$21.debug(`Set trace context to proxy on port ${instance.port}`);
|
|
1893
1893
|
} catch (e) {
|
|
1894
|
-
logger$
|
|
1894
|
+
logger$21.debug(`Unable to set trace context to proxy on port ${instance.port}: ` + require_dist.errorMessage(e));
|
|
1895
1895
|
}
|
|
1896
1896
|
};
|
|
1897
1897
|
//#endregion
|
|
1898
1898
|
//#region src/opentelemetry-lib/instrumentation/claude-agent-sdk/index.ts
|
|
1899
|
-
const logger$
|
|
1899
|
+
const logger$20 = require_dist.initializeLogger();
|
|
1900
1900
|
/**
|
|
1901
1901
|
* Create an instrumented version of the claude-agent-sdk query function.
|
|
1902
1902
|
* This can be used when importing the query function before Laminar initialization.
|
|
@@ -1932,9 +1932,9 @@ function instrumentClaudeAgentQuery(originalQuery) {
|
|
|
1932
1932
|
targetUrl
|
|
1933
1933
|
});
|
|
1934
1934
|
if (proxyInstance && targetUrl) {
|
|
1935
|
-
logger$
|
|
1935
|
+
logger$20.debug(`Using proxy on port ${proxyInstance.port}`);
|
|
1936
1936
|
await Laminar.withSpan(span, async () => {
|
|
1937
|
-
logger$
|
|
1937
|
+
logger$20.debug("Setting trace to proxy instance...");
|
|
1938
1938
|
await setTraceToProxyInstance(proxyInstance);
|
|
1939
1939
|
});
|
|
1940
1940
|
const varsToRemove = getEnvVarsToRemove(mergedEnv, sessionCwd, settingSources);
|
|
@@ -1949,13 +1949,13 @@ function instrumentClaudeAgentQuery(originalQuery) {
|
|
|
1949
1949
|
if (isProviderEnabledInEnv(subprocessEnv, "CLAUDE_CODE_USE_BEDROCK")) subprocessEnv.ANTHROPIC_BEDROCK_BASE_URL = proxyInstance.baseUrl;
|
|
1950
1950
|
if (isProviderEnabledInEnv(subprocessEnv, "CLAUDE_CODE_USE_VERTEX")) subprocessEnv.ANTHROPIC_VERTEX_BASE_URL = proxyInstance.baseUrl;
|
|
1951
1951
|
const flagSettings = buildProxyFlagSettings(callerSettings, proxyInstance.baseUrl, sessionCwd, settingSources);
|
|
1952
|
-
if (flagSettings === null) logger$
|
|
1952
|
+
if (flagSettings === null) logger$20.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.`);
|
|
1953
1953
|
else {
|
|
1954
1954
|
params.options.settings = flagSettings;
|
|
1955
1955
|
const conflicting = Object.entries(readClaudeSettingsEnv(sessionCwd, settingSources)).filter(([key, value]) => PROXY_BASE_URL_ENV_KEYS.includes(key) && value !== "" && value !== proxyInstance.baseUrl).map(([key]) => key);
|
|
1956
|
-
if (conflicting.length > 0) logger$
|
|
1956
|
+
if (conflicting.length > 0) logger$20.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.`);
|
|
1957
1957
|
}
|
|
1958
|
-
} else logger$
|
|
1958
|
+
} else logger$20.debug("No claude proxy server available. Proceeding without proxy.");
|
|
1959
1959
|
const originalGenerator = originalQuery(params);
|
|
1960
1960
|
for await (const message of originalGenerator) {
|
|
1961
1961
|
collected.push(message);
|
|
@@ -1984,7 +1984,7 @@ var ClaudeAgentSDKInstrumentation = class extends _opentelemetry_instrumentation
|
|
|
1984
1984
|
}
|
|
1985
1985
|
manuallyInstrument(claudeAgentModule) {
|
|
1986
1986
|
if (claudeAgentModule.query && typeof claudeAgentModule.query === "function") this._wrap(claudeAgentModule, "query", this.patchQuery());
|
|
1987
|
-
else logger$
|
|
1987
|
+
else logger$20.debug("query function not found in claudeAgentSDK module, skipping instrumentation");
|
|
1988
1988
|
}
|
|
1989
1989
|
patchQuery() {
|
|
1990
1990
|
return (original) => instrumentClaudeAgentQuery(original);
|
|
@@ -2002,7 +2002,7 @@ var ClaudeAgentSDKInstrumentation = class extends _opentelemetry_instrumentation
|
|
|
2002
2002
|
//#endregion
|
|
2003
2003
|
//#region src/laminar.ts
|
|
2004
2004
|
require_dist.loadEnv();
|
|
2005
|
-
const logger$
|
|
2005
|
+
const logger$19 = require_dist.initializeLogger();
|
|
2006
2006
|
var Laminar = class Laminar {
|
|
2007
2007
|
static {
|
|
2008
2008
|
this.isInitialized = false;
|
|
@@ -2088,7 +2088,7 @@ var Laminar = class Laminar {
|
|
|
2088
2088
|
*/
|
|
2089
2089
|
static initialize({ projectApiKey, baseUrl, baseHttpUrl, httpPort, grpcPort, instrumentModules, disableBatch, traceExportTimeoutMillis, logLevel, maxExportBatchSize, forceHttp, sessionRecordingOptions, metadata, inheritGlobalContext, spanProcessor } = {}) {
|
|
2090
2090
|
if (this.isInitialized) {
|
|
2091
|
-
logger$
|
|
2091
|
+
logger$19.warn("Laminar has already been initialized. Skipping initialization.");
|
|
2092
2092
|
return;
|
|
2093
2093
|
}
|
|
2094
2094
|
const key = projectApiKey ?? process?.env?.LMNR_PROJECT_API_KEY;
|
|
@@ -2112,7 +2112,7 @@ var Laminar = class Laminar {
|
|
|
2112
2112
|
...metadata ?? {}
|
|
2113
2113
|
};
|
|
2114
2114
|
if (inheritGlobalContext) LaminarContextManager.inheritGlobalContext = true;
|
|
2115
|
-
if (spanProcessor && !(spanProcessor instanceof LaminarSpanProcessor)) logger$
|
|
2115
|
+
if (spanProcessor && !(spanProcessor instanceof LaminarSpanProcessor)) logger$19.warn("Span processor is not a LaminarSpanProcessor. Some functionality may be impaired.");
|
|
2116
2116
|
this.isInitialized = true;
|
|
2117
2117
|
const urlWithoutSlash = url?.replace(/\/$/, "").replace(/:\d{1,5}$/g, "");
|
|
2118
2118
|
const httpUrlWithoutSlash = httpUrl?.replace(/\/$/, "").replace(/:\d{1,5}$/g, "");
|
|
@@ -2157,11 +2157,11 @@ var Laminar = class Laminar {
|
|
|
2157
2157
|
try {
|
|
2158
2158
|
getRuntime()?.recordTraceId(require_dist.otelTraceIdToUUID(otelSpanContext.traceId));
|
|
2159
2159
|
} catch (e) {
|
|
2160
|
-
logger$
|
|
2160
|
+
logger$19.debug("Failed to record debug trace id from env: " + require_dist.errorMessage(e));
|
|
2161
2161
|
}
|
|
2162
|
-
logger$
|
|
2162
|
+
logger$19.debug("Initialized Laminar parent context from LMNR_SPAN_CONTEXT.");
|
|
2163
2163
|
} catch (e) {
|
|
2164
|
-
logger$
|
|
2164
|
+
logger$19.warn("LMNR_SPAN_CONTEXT is set but could not be used: " + require_dist.errorMessage(e));
|
|
2165
2165
|
}
|
|
2166
2166
|
}
|
|
2167
2167
|
/**
|
|
@@ -2205,14 +2205,14 @@ var Laminar = class Laminar {
|
|
|
2205
2205
|
if (projectId) {
|
|
2206
2206
|
runtime.recordProjectId(projectId);
|
|
2207
2207
|
const sessionUrl = runtime.debuggerSessionUrl();
|
|
2208
|
-
logger$
|
|
2208
|
+
logger$19.info(`Laminar debugger session: ${sessionUrl}`);
|
|
2209
2209
|
if (runtime.shouldOpenBrowser) (0, node_child_process.spawn)(process.platform === "win32" ? "start" : process.platform === "darwin" ? "open" : "xdg-open", [sessionUrl], {
|
|
2210
2210
|
detached: true,
|
|
2211
2211
|
stdio: "ignore"
|
|
2212
2212
|
}).unref();
|
|
2213
2213
|
}
|
|
2214
2214
|
}).catch((e) => {
|
|
2215
|
-
logger$
|
|
2215
|
+
logger$19.warn("Failed to register debug session: " + require_dist.errorMessage(e));
|
|
2216
2216
|
});
|
|
2217
2217
|
this.globalMetadata = {
|
|
2218
2218
|
...this.globalMetadata,
|
|
@@ -2222,7 +2222,7 @@ var Laminar = class Laminar {
|
|
|
2222
2222
|
this.debugExitHook = () => runtime.emitPointer();
|
|
2223
2223
|
process.once("exit", this.debugExitHook);
|
|
2224
2224
|
} catch (e) {
|
|
2225
|
-
logger$
|
|
2225
|
+
logger$19.warn("Failed to initialize debug runtime: " + require_dist.errorMessage(e));
|
|
2226
2226
|
}
|
|
2227
2227
|
}
|
|
2228
2228
|
/**
|
|
@@ -2267,7 +2267,7 @@ var Laminar = class Laminar {
|
|
|
2267
2267
|
runtime.rolloutSessions.register({ sessionId: runtime.sessionId }).then((projectId) => {
|
|
2268
2268
|
if (projectId) runtime.recordProjectId(projectId);
|
|
2269
2269
|
}).catch((e) => {
|
|
2270
|
-
logger$
|
|
2270
|
+
logger$19.debug("Failed to register downstream debug session: " + require_dist.errorMessage(e));
|
|
2271
2271
|
});
|
|
2272
2272
|
this.globalMetadata = {
|
|
2273
2273
|
...this.globalMetadata,
|
|
@@ -2276,7 +2276,7 @@ var Laminar = class Laminar {
|
|
|
2276
2276
|
LaminarContextManager.setGlobalMetadata(this.globalMetadata);
|
|
2277
2277
|
}
|
|
2278
2278
|
} catch (e) {
|
|
2279
|
-
logger$
|
|
2279
|
+
logger$19.debug("Failed to arm debug runtime from context: " + require_dist.errorMessage(e));
|
|
2280
2280
|
}
|
|
2281
2281
|
}
|
|
2282
2282
|
/**
|
|
@@ -2291,7 +2291,7 @@ var Laminar = class Laminar {
|
|
|
2291
2291
|
*/
|
|
2292
2292
|
static patch(modules) {
|
|
2293
2293
|
if (!this.isInitialized) {
|
|
2294
|
-
logger$
|
|
2294
|
+
logger$19.warn("Laminar must be initialized before patching modules. Skipping patch.");
|
|
2295
2295
|
return;
|
|
2296
2296
|
}
|
|
2297
2297
|
if (!modules || Object.keys(modules).length === 0) throw new Error("Pass at least one module to patch");
|
|
@@ -2551,7 +2551,7 @@ var Laminar = class Laminar {
|
|
|
2551
2551
|
const spanContext = require_dist.tryToOtelSpanContext(laminarContext);
|
|
2552
2552
|
entityContext = _opentelemetry_api.trace.setSpan(entityContext, _opentelemetry_api.trace.wrapSpanContext(spanContext));
|
|
2553
2553
|
} catch (e) {
|
|
2554
|
-
logger$
|
|
2554
|
+
logger$19.warn("Failed to parse parent span context: " + require_dist.errorMessage(e));
|
|
2555
2555
|
}
|
|
2556
2556
|
const tagProperties = tags ? { [`${require_dist.ASSOCIATION_PROPERTIES}.tags`]: Array.from(new Set(tags)) } : {};
|
|
2557
2557
|
const ctxAssociationProperties = LaminarContextManager.getAssociationProperties();
|
|
@@ -2654,13 +2654,13 @@ var Laminar = class Laminar {
|
|
|
2654
2654
|
}
|
|
2655
2655
|
static async flush() {
|
|
2656
2656
|
if (this.isInitialized) {
|
|
2657
|
-
logger$
|
|
2657
|
+
logger$19.debug("Flushing spans");
|
|
2658
2658
|
await forceFlush();
|
|
2659
2659
|
}
|
|
2660
2660
|
}
|
|
2661
2661
|
static async shutdown() {
|
|
2662
2662
|
if (this.isInitialized) {
|
|
2663
|
-
logger$
|
|
2663
|
+
logger$19.debug("Shutting down Laminar");
|
|
2664
2664
|
getRuntime()?.emitPointer();
|
|
2665
2665
|
await forceFlush();
|
|
2666
2666
|
this.isInitialized = false;
|
|
@@ -2795,7 +2795,7 @@ return module.exports;
|
|
|
2795
2795
|
//#endregion
|
|
2796
2796
|
//#region src/browser/utils.ts
|
|
2797
2797
|
const LMNR_SEND_EVENTS_FUNCTION_NAME = "lmnrSendEvents";
|
|
2798
|
-
const logger$
|
|
2798
|
+
const logger$18 = require_dist.initializeLogger();
|
|
2799
2799
|
/**
|
|
2800
2800
|
* If the first argument is a string, return an object with the name of the method
|
|
2801
2801
|
* and the argument as the value.
|
|
@@ -2818,7 +2818,7 @@ const takeFullSnapshot = async (page) => await page.evaluate(() => {
|
|
|
2818
2818
|
window.lmnrRrweb.record.takeFullSnapshot();
|
|
2819
2819
|
return true;
|
|
2820
2820
|
} catch (error) {
|
|
2821
|
-
logger$
|
|
2821
|
+
logger$18.error("Error taking full snapshot: " + require_dist.errorMessage(error));
|
|
2822
2822
|
return false;
|
|
2823
2823
|
}
|
|
2824
2824
|
return false;
|
|
@@ -2829,7 +2829,7 @@ const injectSessionRecorder = async (page, sessionRecordingOptions) => {
|
|
|
2829
2829
|
try {
|
|
2830
2830
|
return await script();
|
|
2831
2831
|
} catch (error) {
|
|
2832
|
-
logger$
|
|
2832
|
+
logger$18.error("Operation " + script.name + " failed: " + require_dist.errorMessage(error));
|
|
2833
2833
|
}
|
|
2834
2834
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
2835
2835
|
}
|
|
@@ -2839,20 +2839,20 @@ const injectSessionRecorder = async (page, sessionRecordingOptions) => {
|
|
|
2839
2839
|
try {
|
|
2840
2840
|
isRrwebPresent = await castedPage.evaluate(() => typeof window.lmnrRrweb !== "undefined");
|
|
2841
2841
|
} catch (error) {
|
|
2842
|
-
logger$
|
|
2842
|
+
logger$18.debug("Failed to check if session recorder is loaded: " + require_dist.errorMessage(error));
|
|
2843
2843
|
}
|
|
2844
2844
|
if (!isRrwebPresent) {
|
|
2845
2845
|
if (!await tryRunScript(async function injectSessionRecorder() {
|
|
2846
2846
|
await castedPage.evaluate(RECORDER);
|
|
2847
2847
|
return true;
|
|
2848
2848
|
})) {
|
|
2849
|
-
logger$
|
|
2849
|
+
logger$18.error("Failed to load session recorder");
|
|
2850
2850
|
return;
|
|
2851
2851
|
}
|
|
2852
2852
|
try {
|
|
2853
2853
|
await castedPage.evaluate(injectScript, sessionRecordingOptions);
|
|
2854
2854
|
} catch (error) {
|
|
2855
|
-
logger$
|
|
2855
|
+
logger$18.debug("Failed to inject session recorder: " + require_dist.errorMessage(error));
|
|
2856
2856
|
}
|
|
2857
2857
|
}
|
|
2858
2858
|
};
|
|
@@ -3115,7 +3115,7 @@ async function sendEvents(chunk, client, chunkBuffers, sessionId, traceId) {
|
|
|
3115
3115
|
try {
|
|
3116
3116
|
const { batchId, chunkIndex, totalChunks, data } = chunk;
|
|
3117
3117
|
if (!sessionId || !traceId) {
|
|
3118
|
-
logger$
|
|
3118
|
+
logger$18.debug("Missing sessionId or traceId in chunk");
|
|
3119
3119
|
return;
|
|
3120
3120
|
}
|
|
3121
3121
|
if (!chunkBuffers.has(batchId)) chunkBuffers.set(batchId, {
|
|
@@ -3134,7 +3134,7 @@ async function sendEvents(chunk, client, chunkBuffers, sessionId, traceId) {
|
|
|
3134
3134
|
traceId,
|
|
3135
3135
|
events
|
|
3136
3136
|
}).catch((error) => {
|
|
3137
|
-
logger$
|
|
3137
|
+
logger$18.debug("Failed to send events: " + require_dist.errorMessage(error));
|
|
3138
3138
|
});
|
|
3139
3139
|
chunkBuffers.delete(batchId);
|
|
3140
3140
|
}
|
|
@@ -3142,16 +3142,16 @@ async function sendEvents(chunk, client, chunkBuffers, sessionId, traceId) {
|
|
|
3142
3142
|
const toDelete = [];
|
|
3143
3143
|
for (const [bid, buffer] of chunkBuffers.entries()) if (currentTime - buffer.timestamp > OLD_BUFFER_TIMEOUT) toDelete.push(bid);
|
|
3144
3144
|
for (const bid of toDelete) {
|
|
3145
|
-
logger$
|
|
3145
|
+
logger$18.debug(`Cleaning up incomplete chunk buffer: ${bid}`);
|
|
3146
3146
|
chunkBuffers.delete(bid);
|
|
3147
3147
|
}
|
|
3148
3148
|
} catch (error) {
|
|
3149
|
-
logger$
|
|
3149
|
+
logger$18.debug("Could not send events: " + require_dist.errorMessage(error));
|
|
3150
3150
|
}
|
|
3151
3151
|
}
|
|
3152
3152
|
//#endregion
|
|
3153
3153
|
//#region src/browser/playwright.ts
|
|
3154
|
-
const logger$
|
|
3154
|
+
const logger$17 = require_dist.initializeLogger();
|
|
3155
3155
|
var PlaywrightInstrumentation = class extends _opentelemetry_instrumentation.InstrumentationBase {
|
|
3156
3156
|
constructor(client, sessionRecordingOptions) {
|
|
3157
3157
|
super("@lmnr/playwright-instrumentation", require_dist.version, { enabled: true });
|
|
@@ -3259,7 +3259,7 @@ var PlaywrightInstrumentation = class extends _opentelemetry_instrumentation.Ins
|
|
|
3259
3259
|
try {
|
|
3260
3260
|
await injectSessionRecorder(page, this._sessionRecordingOptions);
|
|
3261
3261
|
} catch (error) {
|
|
3262
|
-
logger$
|
|
3262
|
+
logger$17.error("Error in onLoad handler: " + require_dist.errorMessage(error));
|
|
3263
3263
|
}
|
|
3264
3264
|
});
|
|
3265
3265
|
const chunkBuffers = /* @__PURE__ */ new Map();
|
|
@@ -3269,7 +3269,7 @@ var PlaywrightInstrumentation = class extends _opentelemetry_instrumentation.Ins
|
|
|
3269
3269
|
await sendEvents(chunk, this._client, chunkBuffers, sessionId, traceId);
|
|
3270
3270
|
});
|
|
3271
3271
|
} catch (error) {
|
|
3272
|
-
logger$
|
|
3272
|
+
logger$17.debug("Could not expose function lmnrSendEvents: " + require_dist.errorMessage(error));
|
|
3273
3273
|
}
|
|
3274
3274
|
}
|
|
3275
3275
|
};
|
|
@@ -3694,7 +3694,7 @@ var StagehandV2Instrumentation = class extends _opentelemetry_instrumentation.In
|
|
|
3694
3694
|
};
|
|
3695
3695
|
//#endregion
|
|
3696
3696
|
//#region src/browser/puppeteer.ts
|
|
3697
|
-
const logger$
|
|
3697
|
+
const logger$16 = require_dist.initializeLogger();
|
|
3698
3698
|
var PuppeteerInstrumentation = class extends _opentelemetry_instrumentation.InstrumentationBase {
|
|
3699
3699
|
constructor(client, sessionRecordingOptions) {
|
|
3700
3700
|
super("@lmnr/puppeteer-instrumentation", require_dist.version, { enabled: true });
|
|
@@ -3739,10 +3739,10 @@ var PuppeteerInstrumentation = class extends _opentelemetry_instrumentation.Inst
|
|
|
3739
3739
|
context.on("targetcreated", (target) => {
|
|
3740
3740
|
target.page().then((page) => {
|
|
3741
3741
|
if (page) plugin.patchPage(page, sessionId).catch((error) => {
|
|
3742
|
-
logger$
|
|
3742
|
+
logger$16.error("Failed to patch page: " + require_dist.errorMessage(error));
|
|
3743
3743
|
});
|
|
3744
3744
|
}).catch((error) => {
|
|
3745
|
-
logger$
|
|
3745
|
+
logger$16.error("Failed to patch page: " + require_dist.errorMessage(error));
|
|
3746
3746
|
});
|
|
3747
3747
|
});
|
|
3748
3748
|
await Promise.all((await context.pages()).map((page) => plugin.patchPage(page, sessionId)));
|
|
@@ -3760,19 +3760,19 @@ var PuppeteerInstrumentation = class extends _opentelemetry_instrumentation.Inst
|
|
|
3760
3760
|
context.on("targetcreated", (target) => {
|
|
3761
3761
|
target.page().then((page) => {
|
|
3762
3762
|
if (page) plugin.patchPage(page, sessionId).catch((error) => {
|
|
3763
|
-
logger$
|
|
3763
|
+
logger$16.error("Failed to patch page: " + require_dist.errorMessage(error));
|
|
3764
3764
|
});
|
|
3765
3765
|
}).catch((error) => {
|
|
3766
|
-
logger$
|
|
3766
|
+
logger$16.error("Failed to patch page: " + require_dist.errorMessage(error));
|
|
3767
3767
|
});
|
|
3768
3768
|
});
|
|
3769
3769
|
context.on("targetchanged", (target) => {
|
|
3770
3770
|
target.page().then((page) => {
|
|
3771
3771
|
if (page) plugin.patchPage(page, sessionId).catch((error) => {
|
|
3772
|
-
logger$
|
|
3772
|
+
logger$16.error("Failed to patch page: " + require_dist.errorMessage(error));
|
|
3773
3773
|
});
|
|
3774
3774
|
}).catch((error) => {
|
|
3775
|
-
logger$
|
|
3775
|
+
logger$16.error("Failed to patch page: " + require_dist.errorMessage(error));
|
|
3776
3776
|
});
|
|
3777
3777
|
});
|
|
3778
3778
|
for (const page of await context.pages()) await plugin.patchPage(page, sessionId);
|
|
@@ -3796,7 +3796,7 @@ var PuppeteerInstrumentation = class extends _opentelemetry_instrumentation.Inst
|
|
|
3796
3796
|
const traceId = otelTraceId ? require_dist.otelTraceIdToUUID(otelTraceId) : require_dist.NIL_UUID;
|
|
3797
3797
|
page.on("domcontentloaded", () => {
|
|
3798
3798
|
injectSessionRecorder(page, this._sessionRecordingOptions).catch((error) => {
|
|
3799
|
-
logger$
|
|
3799
|
+
logger$16.error("Error in onLoad handler: " + require_dist.errorMessage(error));
|
|
3800
3800
|
});
|
|
3801
3801
|
});
|
|
3802
3802
|
await injectSessionRecorder(page, this._sessionRecordingOptions);
|
|
@@ -3806,13 +3806,13 @@ var PuppeteerInstrumentation = class extends _opentelemetry_instrumentation.Inst
|
|
|
3806
3806
|
await sendEvents(chunk, this._client, chunkBuffers, sessionId, traceId);
|
|
3807
3807
|
});
|
|
3808
3808
|
} catch (error) {
|
|
3809
|
-
logger$
|
|
3809
|
+
logger$16.debug("Could not expose function lmnrSendEvents: " + require_dist.errorMessage(error));
|
|
3810
3810
|
}
|
|
3811
3811
|
}
|
|
3812
3812
|
};
|
|
3813
3813
|
//#endregion
|
|
3814
3814
|
//#region src/browser/stagehand/v3/constants.ts
|
|
3815
|
-
const logger$
|
|
3815
|
+
const logger$15 = require_dist.initializeLogger();
|
|
3816
3816
|
const CDP_OPERATION_TIMEOUT_MS = 1e4;
|
|
3817
3817
|
const SKIP_URL_PATTERNS = [
|
|
3818
3818
|
"about:blank",
|
|
@@ -3863,7 +3863,7 @@ async function getOrCreateIsolatedWorld(page) {
|
|
|
3863
3863
|
frameId
|
|
3864
3864
|
};
|
|
3865
3865
|
} catch (error) {
|
|
3866
|
-
logger$
|
|
3866
|
+
logger$15.debug("Failed to create isolated world: " + require_dist.errorMessage(error));
|
|
3867
3867
|
return null;
|
|
3868
3868
|
}
|
|
3869
3869
|
}
|
|
@@ -3880,7 +3880,7 @@ async function isRecorderPresent(page, contextId) {
|
|
|
3880
3880
|
if (!result) return true;
|
|
3881
3881
|
return result.result?.value === true;
|
|
3882
3882
|
} catch (error) {
|
|
3883
|
-
logger$
|
|
3883
|
+
logger$15.debug("Failed to check if recorder is present: " + require_dist.errorMessage(error));
|
|
3884
3884
|
return true;
|
|
3885
3885
|
}
|
|
3886
3886
|
}
|
|
@@ -3893,21 +3893,21 @@ async function injectRecorderViaCDP(page, state, conn, sessionRecordingOptions,
|
|
|
3893
3893
|
try {
|
|
3894
3894
|
url = page.url();
|
|
3895
3895
|
} catch (error) {
|
|
3896
|
-
logger$
|
|
3896
|
+
logger$15.debug("Failed to get page URL, page might be closed: " + require_dist.errorMessage(error));
|
|
3897
3897
|
return null;
|
|
3898
3898
|
}
|
|
3899
3899
|
if (shouldSkipUrl(url)) {
|
|
3900
|
-
logger$
|
|
3900
|
+
logger$15.debug(`Skipping recorder injection for URL: ${url}`);
|
|
3901
3901
|
return null;
|
|
3902
3902
|
}
|
|
3903
3903
|
const worldResult = await getOrCreateIsolatedWorld(page);
|
|
3904
3904
|
if (!worldResult) {
|
|
3905
|
-
logger$
|
|
3905
|
+
logger$15.debug("Failed to get isolated world for page");
|
|
3906
3906
|
return null;
|
|
3907
3907
|
}
|
|
3908
3908
|
const { contextId, frameId } = worldResult;
|
|
3909
3909
|
if (await isRecorderPresent(page, contextId)) {
|
|
3910
|
-
logger$
|
|
3910
|
+
logger$15.debug("Recorder already present, skipping injection");
|
|
3911
3911
|
state.contextIdToSession.set(contextId, {
|
|
3912
3912
|
sessionId: state.sessionId,
|
|
3913
3913
|
traceId: state.traceId
|
|
@@ -3920,7 +3920,7 @@ async function injectRecorderViaCDP(page, state, conn, sessionRecordingOptions,
|
|
|
3920
3920
|
contextId
|
|
3921
3921
|
});
|
|
3922
3922
|
} catch (error) {
|
|
3923
|
-
logger$
|
|
3923
|
+
logger$15.debug("Failed to inject rrweb: " + require_dist.errorMessage(error));
|
|
3924
3924
|
return null;
|
|
3925
3925
|
}
|
|
3926
3926
|
const optionsJson = JSON.stringify(sessionRecordingOptions ?? {});
|
|
@@ -3931,14 +3931,14 @@ async function injectRecorderViaCDP(page, state, conn, sessionRecordingOptions,
|
|
|
3931
3931
|
contextId
|
|
3932
3932
|
});
|
|
3933
3933
|
} catch (error) {
|
|
3934
|
-
logger$
|
|
3934
|
+
logger$15.debug("Failed to inject recording setup: " + require_dist.errorMessage(error));
|
|
3935
3935
|
return null;
|
|
3936
3936
|
}
|
|
3937
3937
|
try {
|
|
3938
3938
|
await sendCDP(page, "Runtime.addBinding", { name: "lmnrSendEvents" });
|
|
3939
|
-
logger$
|
|
3939
|
+
logger$15.debug(`Added binding 'lmnrSendEvents' for page ${frameId}, context ${contextId}`);
|
|
3940
3940
|
} catch (error) {
|
|
3941
|
-
logger$
|
|
3941
|
+
logger$15.debug("Binding may already exist: " + require_dist.errorMessage(error));
|
|
3942
3942
|
}
|
|
3943
3943
|
if (bindingHandler) try {
|
|
3944
3944
|
const pageTargetId = page.targetId();
|
|
@@ -3948,26 +3948,26 @@ async function injectRecorderViaCDP(page, state, conn, sessionRecordingOptions,
|
|
|
3948
3948
|
const sessionTyped = session;
|
|
3949
3949
|
if (sessionTyped.on) {
|
|
3950
3950
|
sessionTyped.on("Runtime.bindingCalled", bindingHandler);
|
|
3951
|
-
logger$
|
|
3951
|
+
logger$15.debug(`Set up binding handler on session ${sessionId}`);
|
|
3952
3952
|
}
|
|
3953
3953
|
} catch (error) {
|
|
3954
|
-
logger$
|
|
3954
|
+
logger$15.debug(`Failed to set up binding handler on session ${sessionId}: ` + require_dist.errorMessage(error));
|
|
3955
3955
|
}
|
|
3956
3956
|
state.pageSessionHandlers.set(pageTargetId, bindingHandler);
|
|
3957
3957
|
}
|
|
3958
3958
|
} catch (error) {
|
|
3959
|
-
logger$
|
|
3959
|
+
logger$15.debug("Failed to set up binding handler: " + require_dist.errorMessage(error));
|
|
3960
3960
|
}
|
|
3961
3961
|
state.contextIdToSession.set(contextId, {
|
|
3962
3962
|
sessionId: state.sessionId,
|
|
3963
3963
|
traceId: state.traceId
|
|
3964
3964
|
});
|
|
3965
|
-
logger$
|
|
3965
|
+
logger$15.debug(`Registered context mapping: contextId=${contextId}, sessionId=${state.sessionId}`);
|
|
3966
3966
|
state.instrumentedPageIds.add(frameId);
|
|
3967
|
-
logger$
|
|
3967
|
+
logger$15.debug(`Successfully injected recorder into page ${frameId}`);
|
|
3968
3968
|
return contextId;
|
|
3969
3969
|
} catch (error) {
|
|
3970
|
-
logger$
|
|
3970
|
+
logger$15.debug("Error injecting recorder: " + require_dist.errorMessage(error));
|
|
3971
3971
|
return null;
|
|
3972
3972
|
}
|
|
3973
3973
|
}
|
|
@@ -3981,13 +3981,13 @@ function createBindingHandler(state) {
|
|
|
3981
3981
|
if (event.name !== "lmnrSendEvents") return;
|
|
3982
3982
|
const sessionInfo = state.contextIdToSession.get(event.executionContextId);
|
|
3983
3983
|
if (!sessionInfo) {
|
|
3984
|
-
logger$
|
|
3984
|
+
logger$15.debug("No session info found for context ID: " + event.executionContextId);
|
|
3985
3985
|
if (state.contextIdToSession.size > 0) {
|
|
3986
3986
|
const [, fallbackInfo] = state.contextIdToSession.entries().next().value;
|
|
3987
3987
|
if (fallbackInfo) try {
|
|
3988
3988
|
sendEvents(JSON.parse(event.payload), state.client, state.chunkBuffers, fallbackInfo.sessionId, fallbackInfo.traceId);
|
|
3989
3989
|
} catch (error) {
|
|
3990
|
-
logger$
|
|
3990
|
+
logger$15.debug("Failed to parse binding payload: " + require_dist.errorMessage(error));
|
|
3991
3991
|
}
|
|
3992
3992
|
}
|
|
3993
3993
|
return;
|
|
@@ -3995,7 +3995,7 @@ function createBindingHandler(state) {
|
|
|
3995
3995
|
try {
|
|
3996
3996
|
sendEvents(JSON.parse(event.payload), state.client, state.chunkBuffers, sessionInfo.sessionId, sessionInfo.traceId);
|
|
3997
3997
|
} catch (error) {
|
|
3998
|
-
logger$
|
|
3998
|
+
logger$15.debug("Failed to handle binding event: " + require_dist.errorMessage(error));
|
|
3999
3999
|
}
|
|
4000
4000
|
};
|
|
4001
4001
|
}
|
|
@@ -4011,10 +4011,10 @@ function createTargetCreatedHandler(context, state, sessionRecordingOptions) {
|
|
|
4011
4011
|
const pageId = page.mainFrameId();
|
|
4012
4012
|
if (!state.instrumentedPageIds.has(pageId)) await injectRecorderViaCDP(page, state, context.conn, sessionRecordingOptions, state.bindingHandler ?? void 0);
|
|
4013
4013
|
} catch (error) {
|
|
4014
|
-
logger$
|
|
4014
|
+
logger$15.debug("Error injecting recorder into new page: " + require_dist.errorMessage(error));
|
|
4015
4015
|
}
|
|
4016
4016
|
} catch (error) {
|
|
4017
|
-
logger$
|
|
4017
|
+
logger$15.debug("Error handling target created event: " + require_dist.errorMessage(error));
|
|
4018
4018
|
}
|
|
4019
4019
|
};
|
|
4020
4020
|
}
|
|
@@ -4026,7 +4026,7 @@ function createTargetInfoChangedHandler(context, state, sessionRecordingOptions)
|
|
|
4026
4026
|
if (event.targetInfo.type !== "page") return;
|
|
4027
4027
|
const url = event.targetInfo.url;
|
|
4028
4028
|
if (shouldSkipUrl(url)) return;
|
|
4029
|
-
logger$
|
|
4029
|
+
logger$15.debug(`Target URL changed to ${url}, checking if recorder injection needed`);
|
|
4030
4030
|
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
4031
4031
|
try {
|
|
4032
4032
|
for (const page of context.pages()) if (page.targetId() === event.targetInfo.targetId) {
|
|
@@ -4034,7 +4034,7 @@ function createTargetInfoChangedHandler(context, state, sessionRecordingOptions)
|
|
|
4034
4034
|
break;
|
|
4035
4035
|
}
|
|
4036
4036
|
} catch (error) {
|
|
4037
|
-
logger$
|
|
4037
|
+
logger$15.debug("Error handling target info change: " + require_dist.errorMessage(error));
|
|
4038
4038
|
}
|
|
4039
4039
|
};
|
|
4040
4040
|
}
|
|
@@ -4195,12 +4195,12 @@ var StagehandInstrumentation = class extends _opentelemetry_instrumentation.Inst
|
|
|
4195
4195
|
*/
|
|
4196
4196
|
async setupSessionRecording(stagehandInstance, sessionId, traceId) {
|
|
4197
4197
|
if (!this._client) {
|
|
4198
|
-
logger$
|
|
4198
|
+
logger$15.debug("No Laminar client available, skipping session recording setup");
|
|
4199
4199
|
return;
|
|
4200
4200
|
}
|
|
4201
4201
|
const context = stagehandInstance.context;
|
|
4202
4202
|
if (!context || !context.conn) {
|
|
4203
|
-
logger$
|
|
4203
|
+
logger$15.debug("No context or connection available, skipping session recording setup");
|
|
4204
4204
|
return;
|
|
4205
4205
|
}
|
|
4206
4206
|
const recorderState = {
|
|
@@ -4230,11 +4230,11 @@ var StagehandInstrumentation = class extends _opentelemetry_instrumentation.Inst
|
|
|
4230
4230
|
for (const page of pages) try {
|
|
4231
4231
|
if (await injectRecorderViaCDP(page, recorderState, context.conn, this._sessionRecordingOptions, bindingHandler) !== null) injectedCount++;
|
|
4232
4232
|
} catch (error) {
|
|
4233
|
-
logger$
|
|
4233
|
+
logger$15.debug("Error injecting recorder into page: " + require_dist.errorMessage(error));
|
|
4234
4234
|
}
|
|
4235
|
-
logger$
|
|
4235
|
+
logger$15.debug(`Injected session recorder into ${injectedCount} of ${pages.length} existing page(s)`);
|
|
4236
4236
|
} catch (error) {
|
|
4237
|
-
logger$
|
|
4237
|
+
logger$15.debug("Error accessing pages for recorder injection: " + require_dist.errorMessage(error));
|
|
4238
4238
|
}
|
|
4239
4239
|
}
|
|
4240
4240
|
patchStagehandClose() {
|
|
@@ -4264,12 +4264,12 @@ var StagehandInstrumentation = class extends _opentelemetry_instrumentation.Inst
|
|
|
4264
4264
|
if (recorderState.targetCreatedHandler) try {
|
|
4265
4265
|
context.conn.off("Target.targetCreated", recorderState.targetCreatedHandler);
|
|
4266
4266
|
} catch (error) {
|
|
4267
|
-
logger$
|
|
4267
|
+
logger$15.debug("Error removing target created handler: " + require_dist.errorMessage(error));
|
|
4268
4268
|
}
|
|
4269
4269
|
if (recorderState.targetInfoChangedHandler) try {
|
|
4270
4270
|
context.conn.off("Target.targetInfoChanged", recorderState.targetInfoChangedHandler);
|
|
4271
4271
|
} catch (error) {
|
|
4272
|
-
logger$
|
|
4272
|
+
logger$15.debug("Error removing target info changed handler: " + require_dist.errorMessage(error));
|
|
4273
4273
|
}
|
|
4274
4274
|
}
|
|
4275
4275
|
recorderState.contextIdToSession.clear();
|
|
@@ -4280,7 +4280,7 @@ var StagehandInstrumentation = class extends _opentelemetry_instrumentation.Inst
|
|
|
4280
4280
|
recorderState.targetCreatedHandler = null;
|
|
4281
4281
|
recorderState.targetInfoChangedHandler = null;
|
|
4282
4282
|
this.stagehandInstanceToRecorderState.delete(stagehandInstance);
|
|
4283
|
-
logger$
|
|
4283
|
+
logger$15.debug("Cleaned up session recording for Stagehand instance");
|
|
4284
4284
|
}
|
|
4285
4285
|
patchStagehandGlobalMethod(methodName, sessionId, parentSpan) {
|
|
4286
4286
|
return (original) => async function method(...args) {
|
|
@@ -5151,7 +5151,7 @@ const normalizeMessages = (data, role = "user") => {
|
|
|
5151
5151
|
};
|
|
5152
5152
|
//#endregion
|
|
5153
5153
|
//#region src/opentelemetry-lib/instrumentation/openai-agents/messages.ts
|
|
5154
|
-
const logger$
|
|
5154
|
+
const logger$14 = require_dist.initializeLogger();
|
|
5155
5155
|
const setLmnrSpanIo = (lmnrSpan, inputData, outputData) => {
|
|
5156
5156
|
if (inputData !== void 0 && inputData !== null) lmnrSpan.setAttribute(require_dist.SPAN_INPUT, JSON.stringify(inputData));
|
|
5157
5157
|
if (outputData !== void 0 && outputData !== null) lmnrSpan.setAttribute(require_dist.SPAN_OUTPUT, JSON.stringify(outputData));
|
|
@@ -5180,7 +5180,7 @@ const setGenAiOutputMessagesFromResponse = (lmnrSpan, response) => {
|
|
|
5180
5180
|
if (!outputItems) return;
|
|
5181
5181
|
const id = response.id;
|
|
5182
5182
|
if (!Array.isArray(outputItems)) {
|
|
5183
|
-
logger$
|
|
5183
|
+
logger$14.debug("Laminar OpenAI agents instrumentation, failed to parse output items. Expected array");
|
|
5184
5184
|
outputItems = [];
|
|
5185
5185
|
}
|
|
5186
5186
|
const result = {
|
|
@@ -5375,7 +5375,7 @@ const applySpeechGroupSpanData = (lmnrSpan, spanData) => {
|
|
|
5375
5375
|
};
|
|
5376
5376
|
//#endregion
|
|
5377
5377
|
//#region src/opentelemetry-lib/instrumentation/openai-agents/processor.ts
|
|
5378
|
-
const logger$
|
|
5378
|
+
const logger$13 = require_dist.initializeLogger();
|
|
5379
5379
|
var LaminarAgentsTraceProcessor = class {
|
|
5380
5380
|
constructor() {
|
|
5381
5381
|
this.traces = /* @__PURE__ */ new Map();
|
|
@@ -5393,7 +5393,7 @@ var LaminarAgentsTraceProcessor = class {
|
|
|
5393
5393
|
} catch {}
|
|
5394
5394
|
this.applyTraceMetadata(state.rootSpan, agentsTrace);
|
|
5395
5395
|
} catch (e) {
|
|
5396
|
-
logger$
|
|
5396
|
+
logger$13.debug(`Error in onTraceStart: ${String(e)}`);
|
|
5397
5397
|
}
|
|
5398
5398
|
}
|
|
5399
5399
|
async onTraceEnd(agentsTrace) {
|
|
@@ -5442,7 +5442,7 @@ var LaminarAgentsTraceProcessor = class {
|
|
|
5442
5442
|
});
|
|
5443
5443
|
const key = span.spanId;
|
|
5444
5444
|
if (!key) {
|
|
5445
|
-
logger$
|
|
5445
|
+
logger$13.debug("Span missing spanId, cannot track");
|
|
5446
5446
|
try {
|
|
5447
5447
|
lmnrSpan.end();
|
|
5448
5448
|
} catch {}
|
|
@@ -5461,7 +5461,7 @@ var LaminarAgentsTraceProcessor = class {
|
|
|
5461
5461
|
activationContext
|
|
5462
5462
|
});
|
|
5463
5463
|
} catch (e) {
|
|
5464
|
-
logger$
|
|
5464
|
+
logger$13.debug(`Error in onSpanStart: ${String(e)}`);
|
|
5465
5465
|
if (lmnrSpan !== void 0) try {
|
|
5466
5466
|
lmnrSpan.end();
|
|
5467
5467
|
} catch {}
|
|
@@ -5579,7 +5579,7 @@ var LaminarAgentsTraceProcessor = class {
|
|
|
5579
5579
|
};
|
|
5580
5580
|
//#endregion
|
|
5581
5581
|
//#region src/opentelemetry-lib/instrumentation/openai-agents/index.ts
|
|
5582
|
-
const logger$
|
|
5582
|
+
const logger$12 = require_dist.initializeLogger();
|
|
5583
5583
|
const wrapGetResponse = (original) => function(request, ...rest) {
|
|
5584
5584
|
const systemInstructions = request?.systemInstructions;
|
|
5585
5585
|
return runWithSystemInstructions(systemInstructions, () => original.call(this, request, ...rest));
|
|
@@ -5599,7 +5599,7 @@ var OpenAIAgentsInstrumentation = class extends _opentelemetry_instrumentation.I
|
|
|
5599
5599
|
}
|
|
5600
5600
|
manuallyInstrument(agentsModule) {
|
|
5601
5601
|
if (!agentsModule) {
|
|
5602
|
-
logger$
|
|
5602
|
+
logger$12.debug("@openai/agents module not provided, skipping");
|
|
5603
5603
|
return;
|
|
5604
5604
|
}
|
|
5605
5605
|
this.registerProcessor(agentsModule);
|
|
@@ -5609,7 +5609,7 @@ var OpenAIAgentsInstrumentation = class extends _opentelemetry_instrumentation.I
|
|
|
5609
5609
|
if (this._processor !== void 0) return;
|
|
5610
5610
|
const addTraceProcessor = module.addTraceProcessor;
|
|
5611
5611
|
if (typeof addTraceProcessor !== "function") {
|
|
5612
|
-
logger$
|
|
5612
|
+
logger$12.debug("addTraceProcessor not found in @openai/agents module");
|
|
5613
5613
|
return;
|
|
5614
5614
|
}
|
|
5615
5615
|
try {
|
|
@@ -5617,7 +5617,7 @@ var OpenAIAgentsInstrumentation = class extends _opentelemetry_instrumentation.I
|
|
|
5617
5617
|
addTraceProcessor(processor);
|
|
5618
5618
|
this._processor = processor;
|
|
5619
5619
|
} catch (e) {
|
|
5620
|
-
logger$
|
|
5620
|
+
logger$12.debug(`Failed to register Laminar Agents processor: ${String(e)}`);
|
|
5621
5621
|
}
|
|
5622
5622
|
}
|
|
5623
5623
|
patchModel(module) {
|
|
@@ -5630,7 +5630,7 @@ var OpenAIAgentsInstrumentation = class extends _opentelemetry_instrumentation.I
|
|
|
5630
5630
|
try {
|
|
5631
5631
|
this._wrap(cls.prototype, method, wrapper);
|
|
5632
5632
|
} catch (e) {
|
|
5633
|
-
logger$
|
|
5633
|
+
logger$12.debug(`Failed to wrap ${method}: ${String(e)}`);
|
|
5634
5634
|
}
|
|
5635
5635
|
}
|
|
5636
5636
|
this._wrappedPrototypes.add(cls.prototype);
|
|
@@ -5736,7 +5736,7 @@ const getLangVersion = () => {
|
|
|
5736
5736
|
};
|
|
5737
5737
|
//#endregion
|
|
5738
5738
|
//#region src/opentelemetry-lib/tracing/exporter.ts
|
|
5739
|
-
const logger$
|
|
5739
|
+
const logger$11 = require_dist.initializeLogger();
|
|
5740
5740
|
var LaminarSpanExporter = class {
|
|
5741
5741
|
constructor(options = {}) {
|
|
5742
5742
|
let url = options.baseUrl ?? process?.env?.LMNR_BASE_URL;
|
|
@@ -5756,7 +5756,7 @@ var LaminarSpanExporter = class {
|
|
|
5756
5756
|
const otelProtocol = require_dist.getOtelEnvVar("PROTOCOL") || "grpc/protobuf";
|
|
5757
5757
|
const otelExporter = process?.env?.OTEL_EXPORTER;
|
|
5758
5758
|
forceHttp = otelProtocol === "http/protobuf" || otelProtocol === "http/json" || otelExporter === "otlp_http";
|
|
5759
|
-
} else if (otelEndpoint && url) logger$
|
|
5759
|
+
} else if (otelEndpoint && url) logger$11.warn("OTEL_ENDPOINT is set, but Laminar base URL is also set. Ignoring OTEL_ENDPOINT.");
|
|
5760
5760
|
}
|
|
5761
5761
|
if (!url) throw new Error("Laminar base URL is not set and OTEL_ENDPOINT is not set. Please either\n- set the LMNR_BASE_URL environment variable\n- set the OTEL_ENDPOINT environment variable (if you are not using a Laminar API key)\n- pass the baseUrl parameter to Laminar.initialize");
|
|
5762
5762
|
if (!port) port = url.match(/:\d{1,5}$/g) ? parseInt(url.match(/:\d{1,5}$/g)[0].slice(1)) : forceHttp ? 443 : 8443;
|
|
@@ -5837,7 +5837,7 @@ var LaminarSpanProcessor = class LaminarSpanProcessor {
|
|
|
5837
5837
|
const parentSpanId = getParentSpanId(span);
|
|
5838
5838
|
const parentSpanPath = parentPathFromAttribute ?? (parentSpanId !== void 0 ? this._spanIdToPath.get(parentSpanId) : void 0);
|
|
5839
5839
|
const spanId = span.spanContext().spanId;
|
|
5840
|
-
const parentSpanIdsPath = parentIdsPathFromAttribute ?? (parentSpanId ? this._spanIdLists.get(parentSpanId) : []);
|
|
5840
|
+
const parentSpanIdsPath = parentIdsPathFromAttribute ?? (parentSpanId ? this._spanIdLists.get(parentSpanId) ?? [require_dist.otelSpanIdToUUID(parentSpanId)] : []);
|
|
5841
5841
|
const spanPath = parentSpanPath ? [...parentSpanPath, span.name] : [span.name];
|
|
5842
5842
|
const spanIdUuid = require_dist.otelSpanIdToUUID(spanId);
|
|
5843
5843
|
const spanIdsPath = parentSpanIdsPath ? [...parentSpanIdsPath, spanIdUuid] : [spanIdUuid];
|
|
@@ -5917,7 +5917,7 @@ var LaminarSpanProcessor = class LaminarSpanProcessor {
|
|
|
5917
5917
|
};
|
|
5918
5918
|
//#endregion
|
|
5919
5919
|
//#region src/opentelemetry-lib/instrumentation/temporal/helpers.ts
|
|
5920
|
-
const logger$
|
|
5920
|
+
const logger$10 = require_dist.initializeLogger();
|
|
5921
5921
|
const _enc = new TextEncoder();
|
|
5922
5922
|
const _dec = new TextDecoder();
|
|
5923
5923
|
const encodePayload = (value) => ({
|
|
@@ -5936,7 +5936,7 @@ const decodePayload = (payload) => {
|
|
|
5936
5936
|
};
|
|
5937
5937
|
/**
|
|
5938
5938
|
* Read the currently active Laminar span and encode its context into a headers
|
|
5939
|
-
* map. Writes both `
|
|
5939
|
+
* map. Writes both `x-lmnr-span-context` (full Laminar JSON) and
|
|
5940
5940
|
* `traceparent` (W3C, for interop with non-Laminar workers).
|
|
5941
5941
|
*
|
|
5942
5942
|
* Returns the headers map unchanged if there is no active Laminar span.
|
|
@@ -5959,7 +5959,7 @@ const buildHeaders = (existing) => {
|
|
|
5959
5959
|
return headers;
|
|
5960
5960
|
};
|
|
5961
5961
|
/**
|
|
5962
|
-
* Read `
|
|
5962
|
+
* Read `x-lmnr-span-context` (preferred) or `traceparent` (fallback) from
|
|
5963
5963
|
* Temporal headers and push the restored context onto Laminar's ALS stack.
|
|
5964
5964
|
*
|
|
5965
5965
|
* Returns the restored context (Laminar + OTel) or `undefined` if headers
|
|
@@ -5975,7 +5975,7 @@ const restoreContextFromHeaders = (headers) => {
|
|
|
5975
5975
|
otelContext: pushLaminarContext(ctx)
|
|
5976
5976
|
};
|
|
5977
5977
|
} catch (e) {
|
|
5978
|
-
logger$
|
|
5978
|
+
logger$10.warn(`[Laminar] Could not restore ${require_consts.LAMINAR_SPAN_CONTEXT_HEADER}: ${require_dist.errorMessage(e)}`);
|
|
5979
5979
|
}
|
|
5980
5980
|
const traceparent = decodePayload(headers[require_consts.TRACEPARENT_HEADER]);
|
|
5981
5981
|
if (traceparent) {
|
|
@@ -5993,7 +5993,7 @@ const restoreContextFromHeaders = (headers) => {
|
|
|
5993
5993
|
otelContext: pushLaminarContext(ctx)
|
|
5994
5994
|
};
|
|
5995
5995
|
} catch (e) {
|
|
5996
|
-
logger$
|
|
5996
|
+
logger$10.warn(`[Laminar] Could not restore traceparent: ${require_dist.errorMessage(e)}`);
|
|
5997
5997
|
}
|
|
5998
5998
|
}
|
|
5999
5999
|
}
|
|
@@ -6187,7 +6187,7 @@ var ActivityInboundInterceptor = class {
|
|
|
6187
6187
|
const ActivityInterceptorFactory = (options) => (ctx) => ({ inbound: new ActivityInboundInterceptor(options, ctx) });
|
|
6188
6188
|
//#endregion
|
|
6189
6189
|
//#region src/opentelemetry-lib/instrumentation/temporal/workflow-span.ts
|
|
6190
|
-
const logger$
|
|
6190
|
+
const logger$9 = require_dist.initializeLogger();
|
|
6191
6191
|
const _patchedWorkflowClients = /* @__PURE__ */ new WeakSet();
|
|
6192
6192
|
const workflowName = (args) => {
|
|
6193
6193
|
const wf = args[0];
|
|
@@ -6211,7 +6211,7 @@ const wrapHandle = (handle, span) => {
|
|
|
6211
6211
|
try {
|
|
6212
6212
|
return Laminar.serializeLaminarSpanContext(span) ?? void 0;
|
|
6213
6213
|
} catch (e) {
|
|
6214
|
-
logger$
|
|
6214
|
+
logger$9.debug(`failed to derive workflow child span parent: ${require_dist.errorMessage(e)}`);
|
|
6215
6215
|
return;
|
|
6216
6216
|
}
|
|
6217
6217
|
};
|
|
@@ -6223,7 +6223,7 @@ const wrapHandle = (handle, span) => {
|
|
|
6223
6223
|
try {
|
|
6224
6224
|
span.setOutput(res);
|
|
6225
6225
|
} catch (e) {
|
|
6226
|
-
logger$
|
|
6226
|
+
logger$9.debug(`failed to set workflow span output: ${require_dist.errorMessage(e)}`);
|
|
6227
6227
|
}
|
|
6228
6228
|
});
|
|
6229
6229
|
return res;
|
|
@@ -6300,7 +6300,7 @@ const patchWorkflowClient = (clientModule) => {
|
|
|
6300
6300
|
try {
|
|
6301
6301
|
span.setOutput(res);
|
|
6302
6302
|
} catch (e) {
|
|
6303
|
-
logger$
|
|
6303
|
+
logger$9.debug(`failed to set workflow span output: ${require_dist.errorMessage(e)}`);
|
|
6304
6304
|
}
|
|
6305
6305
|
span.end();
|
|
6306
6306
|
return res;
|
|
@@ -6384,14 +6384,14 @@ const patchWorkflowClient = (clientModule) => {
|
|
|
6384
6384
|
* const client = new temporalClient.Client({ ... });
|
|
6385
6385
|
* ```
|
|
6386
6386
|
*/
|
|
6387
|
-
const logger$
|
|
6387
|
+
const logger$8 = require_dist.initializeLogger();
|
|
6388
6388
|
const _patchedWorkerModules = /* @__PURE__ */ new WeakSet();
|
|
6389
6389
|
const _patchedClientModules = /* @__PURE__ */ new WeakSet();
|
|
6390
6390
|
let _warnedWorkflowBundleOnce = false;
|
|
6391
6391
|
const warnWorkflowBundleOnce = () => {
|
|
6392
6392
|
if (_warnedWorkflowBundleOnce) return;
|
|
6393
6393
|
_warnedWorkflowBundleOnce = true;
|
|
6394
|
-
logger$
|
|
6394
|
+
logger$8.warn("[Laminar] Temporal Worker.create was called with a pre-built `workflowBundle`; Temporal ignores `interceptors.workflowModules` in that case, so Laminar's workflow interceptor cannot be auto-injected. Trace context from workflow start will NOT propagate to activities or child workflows scheduled inside the workflow. Register the interceptor at bundle time: bundleWorkflowCode({ workflowInterceptorModules: [require.resolve('@lmnr-ai/lmnr/temporal-workflow-interceptors')], ... }).");
|
|
6395
6395
|
};
|
|
6396
6396
|
/**
|
|
6397
6397
|
* Patch a `@temporalio/worker` module object so that every `Worker.create()`
|
|
@@ -6462,7 +6462,7 @@ const LaminarTemporalInterceptors = {
|
|
|
6462
6462
|
};
|
|
6463
6463
|
//#endregion
|
|
6464
6464
|
//#region src/opentelemetry-lib/tracing/instrumentations.ts
|
|
6465
|
-
const logger$
|
|
6465
|
+
const logger$7 = require_dist.initializeLogger();
|
|
6466
6466
|
/**
|
|
6467
6467
|
* Initialize and return Laminar instrumentations.
|
|
6468
6468
|
* Useful to use with libraries that initialize tracing and can register passed
|
|
@@ -6571,7 +6571,7 @@ const manuallyInitInstrumentations = (client, instrumentModules, suppressContent
|
|
|
6571
6571
|
instrumentations.push(anthropicInstrumentation);
|
|
6572
6572
|
anthropicInstrumentation.manuallyInstrument(instrumentModules.anthropic);
|
|
6573
6573
|
}
|
|
6574
|
-
if (instrumentModules?.azureOpenAI) logger$
|
|
6574
|
+
if (instrumentModules?.azureOpenAI) logger$7.warn("Azure OpenAI instrumentation is no longer supported. Not enabling any instrumentation.");
|
|
6575
6575
|
if (instrumentModules?.cohere) {
|
|
6576
6576
|
const cohereInstrumentation = new _traceloop_instrumentation_cohere.CohereInstrumentation({ traceContent: !suppressContentTracing });
|
|
6577
6577
|
instrumentations.push(cohereInstrumentation);
|
|
@@ -6592,7 +6592,7 @@ const manuallyInitInstrumentations = (client, instrumentModules, suppressContent
|
|
|
6592
6592
|
instrumentations.push(langchainInstrumentation);
|
|
6593
6593
|
langchainInstrumentation.manuallyInstrument(instrumentModules.langchain);
|
|
6594
6594
|
}
|
|
6595
|
-
if (instrumentModules?.llamaIndex) logger$
|
|
6595
|
+
if (instrumentModules?.llamaIndex) logger$7.warn("Llamaindex JS is deprecated. Not enabling any instrumentation.");
|
|
6596
6596
|
if (instrumentModules?.chromadb) {
|
|
6597
6597
|
const chromadbInstrumentation = new _traceloop_instrumentation_chromadb.ChromaDBInstrumentation({ traceContent: !suppressContentTracing });
|
|
6598
6598
|
instrumentations.push(chromadbInstrumentation);
|
|
@@ -6702,7 +6702,7 @@ const isGlobalContextManagerConfigured = () => {
|
|
|
6702
6702
|
};
|
|
6703
6703
|
//#endregion
|
|
6704
6704
|
//#region src/opentelemetry-lib/tracing/index.ts
|
|
6705
|
-
const logger$
|
|
6705
|
+
const logger$6 = require_dist.initializeLogger();
|
|
6706
6706
|
let spanProcessor;
|
|
6707
6707
|
let tracerProvider;
|
|
6708
6708
|
let _baseHttpUrl = "https://api.lmnr.ai:443";
|
|
@@ -6750,10 +6750,10 @@ const startTracing = (options) => {
|
|
|
6750
6750
|
const contextManager = new _opentelemetry_context_async_hooks.AsyncLocalStorageContextManager();
|
|
6751
6751
|
contextManager.enable();
|
|
6752
6752
|
_opentelemetry_api.context.setGlobalContextManager(contextManager);
|
|
6753
|
-
logger$
|
|
6753
|
+
logger$6.debug("Laminar set global OTel Context Manager");
|
|
6754
6754
|
}
|
|
6755
|
-
logger$
|
|
6756
|
-
logger$
|
|
6755
|
+
logger$6.debug("Global OTel Context Manager exists");
|
|
6756
|
+
logger$6.debug(`Laminar registering ${instrumentations.length} instrumentations`);
|
|
6757
6757
|
(0, _opentelemetry_instrumentation.registerInstrumentations)({
|
|
6758
6758
|
instrumentations,
|
|
6759
6759
|
tracerProvider: newProvider
|
|
@@ -6823,6 +6823,13 @@ const getTracer = () => {
|
|
|
6823
6823
|
* @returns The span processor, or undefined if not initialized.
|
|
6824
6824
|
*/
|
|
6825
6825
|
const getSpanProcessor = () => spanProcessor;
|
|
6826
|
+
/**
|
|
6827
|
+
* The API key the initialized pipeline exports with. Used internally so an
|
|
6828
|
+
* integration that carries its own credentials can detect that it would ship
|
|
6829
|
+
* spans to a different project than its own API calls.
|
|
6830
|
+
* @returns The API key, or undefined if tracing is not initialized.
|
|
6831
|
+
*/
|
|
6832
|
+
const getConfiguredApiKey = () => _apiKey;
|
|
6826
6833
|
const forceFlush = async () => {
|
|
6827
6834
|
await waitForPendingStreams(5e3);
|
|
6828
6835
|
await spanProcessor.forceFlush();
|
|
@@ -6864,7 +6871,7 @@ const _resetConfiguration = () => {
|
|
|
6864
6871
|
};
|
|
6865
6872
|
//#endregion
|
|
6866
6873
|
//#region src/opentelemetry-lib/tracing/decorators.ts
|
|
6867
|
-
const logger$
|
|
6874
|
+
const logger$5 = require_dist.initializeLogger();
|
|
6868
6875
|
function observeBase({ name, contextProperties, spanAttributes, input, ignoreInput, ignoreOutput, inputParameters, suppressTracing: shouldSuppressTracing, parentSpanContext }, fn, thisArg, ...args) {
|
|
6869
6876
|
let entityContext = LaminarContextManager.getContext();
|
|
6870
6877
|
if (shouldSuppressTracing) entityContext = (0, _opentelemetry_core.suppressTracing)(entityContext);
|
|
@@ -6874,7 +6881,7 @@ function observeBase({ name, contextProperties, spanAttributes, input, ignoreInp
|
|
|
6874
6881
|
const spanContext = require_dist.tryToOtelSpanContext(laminarContext);
|
|
6875
6882
|
entityContext = _opentelemetry_api.trace.setSpan(entityContext, _opentelemetry_api.trace.wrapSpanContext(spanContext));
|
|
6876
6883
|
} catch (e) {
|
|
6877
|
-
logger$
|
|
6884
|
+
logger$5.warn("Failed to parse parent span context: " + require_dist.errorMessage(e));
|
|
6878
6885
|
}
|
|
6879
6886
|
try {
|
|
6880
6887
|
if (contextProperties && Object.keys(contextProperties).length > 0) {
|
|
@@ -6885,7 +6892,7 @@ function observeBase({ name, contextProperties, spanAttributes, input, ignoreInp
|
|
|
6885
6892
|
});
|
|
6886
6893
|
}
|
|
6887
6894
|
} catch (e) {
|
|
6888
|
-
logger$
|
|
6895
|
+
logger$5.warn("Failed to set context properties: " + require_dist.errorMessage(e));
|
|
6889
6896
|
}
|
|
6890
6897
|
return _opentelemetry_api.context.with(entityContext, () => getTracer().startActiveSpan(name, { attributes: spanAttributes }, entityContext, (span) => {
|
|
6891
6898
|
if (shouldSendTraces() && !ignoreInput) try {
|
|
@@ -6894,7 +6901,7 @@ function observeBase({ name, contextProperties, spanAttributes, input, ignoreInp
|
|
|
6894
6901
|
else if (spanInput.length === 1 && typeof spanInput[0] === "object" && !(spanInput[0] instanceof Map)) span.setAttribute(require_dist.SPAN_INPUT, typeof spanInput[0] === "string" ? require_dist.truncateSpanPayload(spanInput[0], "input") : serialize(spanInput[0], "input"));
|
|
6895
6902
|
else span.setAttribute(require_dist.SPAN_INPUT, serialize(spanInput.length > 0 ? spanInput : {}, "input"));
|
|
6896
6903
|
} catch (error) {
|
|
6897
|
-
logger$
|
|
6904
|
+
logger$5.warn("Failed to serialize input: " + require_dist.errorMessage(error));
|
|
6898
6905
|
}
|
|
6899
6906
|
let res;
|
|
6900
6907
|
try {
|
|
@@ -6904,7 +6911,7 @@ function observeBase({ name, contextProperties, spanAttributes, input, ignoreInp
|
|
|
6904
6911
|
span.recordException(error);
|
|
6905
6912
|
span.end();
|
|
6906
6913
|
} catch (error) {
|
|
6907
|
-
logger$
|
|
6914
|
+
logger$5.warn("Failed to record exception and end span: " + require_dist.errorMessage(error));
|
|
6908
6915
|
}
|
|
6909
6916
|
throw error;
|
|
6910
6917
|
}
|
|
@@ -6913,18 +6920,18 @@ function observeBase({ name, contextProperties, spanAttributes, input, ignoreInp
|
|
|
6913
6920
|
try {
|
|
6914
6921
|
streamInfo = getStream(resolvedRes);
|
|
6915
6922
|
} catch (error) {
|
|
6916
|
-
logger$
|
|
6923
|
+
logger$5.warn("Failed to get stream info: " + require_dist.errorMessage(error));
|
|
6917
6924
|
}
|
|
6918
6925
|
if (streamInfo.type !== null) return handleStreamResult(resolvedRes, streamInfo, span, ignoreOutput, serialize);
|
|
6919
6926
|
try {
|
|
6920
6927
|
if (shouldSendTraces() && !ignoreOutput) span.setAttribute(require_dist.SPAN_OUTPUT, serialize(resolvedRes));
|
|
6921
6928
|
} catch (error) {
|
|
6922
|
-
logger$
|
|
6929
|
+
logger$5.warn("Failed to serialize async output: " + require_dist.errorMessage(error));
|
|
6923
6930
|
} finally {
|
|
6924
6931
|
try {
|
|
6925
6932
|
span.end();
|
|
6926
6933
|
} catch (error) {
|
|
6927
|
-
logger$
|
|
6934
|
+
logger$5.warn("Failed to end span: " + require_dist.errorMessage(error));
|
|
6928
6935
|
}
|
|
6929
6936
|
}
|
|
6930
6937
|
return resolvedRes;
|
|
@@ -6933,7 +6940,7 @@ function observeBase({ name, contextProperties, spanAttributes, input, ignoreInp
|
|
|
6933
6940
|
span.recordException(error);
|
|
6934
6941
|
span.end();
|
|
6935
6942
|
} catch (error) {
|
|
6936
|
-
logger$
|
|
6943
|
+
logger$5.warn("Failed to record exception and end span: " + require_dist.errorMessage(error));
|
|
6937
6944
|
}
|
|
6938
6945
|
throw error;
|
|
6939
6946
|
});
|
|
@@ -6941,18 +6948,18 @@ function observeBase({ name, contextProperties, spanAttributes, input, ignoreInp
|
|
|
6941
6948
|
try {
|
|
6942
6949
|
streamInfo = getStream(res);
|
|
6943
6950
|
} catch (error) {
|
|
6944
|
-
logger$
|
|
6951
|
+
logger$5.warn("Failed to get stream info: " + require_dist.errorMessage(error));
|
|
6945
6952
|
}
|
|
6946
6953
|
if (streamInfo.type !== null) return handleStreamResult(res, streamInfo, span, ignoreOutput, serialize);
|
|
6947
6954
|
try {
|
|
6948
6955
|
if (shouldSendTraces() && !ignoreOutput) span.setAttribute(require_dist.SPAN_OUTPUT, typeof res === "string" ? require_dist.truncateSpanPayload(res, "output") : serialize(res));
|
|
6949
6956
|
} catch (error) {
|
|
6950
|
-
logger$
|
|
6957
|
+
logger$5.warn("Failed to serialize output: " + require_dist.errorMessage(error));
|
|
6951
6958
|
} finally {
|
|
6952
6959
|
try {
|
|
6953
6960
|
span.end();
|
|
6954
6961
|
} catch (error) {
|
|
6955
|
-
logger$
|
|
6962
|
+
logger$5.warn("Failed to end span: " + require_dist.errorMessage(error));
|
|
6956
6963
|
}
|
|
6957
6964
|
}
|
|
6958
6965
|
return res;
|
|
@@ -6976,7 +6983,7 @@ const normalizePayload = (payload, seen) => {
|
|
|
6976
6983
|
const serialize = (payload, kind = "output") => require_dist.truncateSpanPayload(JSON.stringify(normalizePayload(payload, /* @__PURE__ */ new WeakSet())), kind);
|
|
6977
6984
|
//#endregion
|
|
6978
6985
|
//#region src/decorators.ts
|
|
6979
|
-
const logger$
|
|
6986
|
+
const logger$4 = require_dist.initializeLogger();
|
|
6980
6987
|
/**
|
|
6981
6988
|
* The main decorator entrypoint for Laminar. This is used to wrap
|
|
6982
6989
|
* functions and methods to create spans.
|
|
@@ -7089,7 +7096,7 @@ const buildContextProperties = (options) => {
|
|
|
7089
7096
|
parentUserId = laminarContext.userId;
|
|
7090
7097
|
parentSessionId = laminarContext.sessionId;
|
|
7091
7098
|
} catch (e) {
|
|
7092
|
-
logger$
|
|
7099
|
+
logger$4.warn("Failed to parse parent span context: " + require_dist.errorMessage(e));
|
|
7093
7100
|
}
|
|
7094
7101
|
const contextProperties = {};
|
|
7095
7102
|
const sessionIdValue = options.sessionId ?? parentSessionId ?? ctxAssociationProperties.sessionId;
|
|
@@ -7126,7 +7133,7 @@ const buildSpanAttributes = (options) => {
|
|
|
7126
7133
|
if (laminarContext.spanPath) spanAttributes[require_dist.PARENT_SPAN_PATH] = laminarContext.spanPath;
|
|
7127
7134
|
if (laminarContext.spanIdsPath) spanAttributes[require_dist.PARENT_SPAN_IDS_PATH] = laminarContext.spanIdsPath;
|
|
7128
7135
|
} catch (e) {
|
|
7129
|
-
logger$
|
|
7136
|
+
logger$4.warn("Failed to parse parent span context for span attributes: " + require_dist.errorMessage(e));
|
|
7130
7137
|
}
|
|
7131
7138
|
return spanAttributes;
|
|
7132
7139
|
};
|
|
@@ -7261,7 +7268,7 @@ function observeExperimentalDecorator(config) {
|
|
|
7261
7268
|
require_dist.loadEnv();
|
|
7262
7269
|
const DEFAULT_CONCURRENCY = 5;
|
|
7263
7270
|
const MAX_EXPORT_BATCH_SIZE = 64;
|
|
7264
|
-
const logger$
|
|
7271
|
+
const logger$3 = require_dist.initializeLogger();
|
|
7265
7272
|
const getEvaluationUrl = (projectId, evaluationId, baseUrl, frontendPort) => {
|
|
7266
7273
|
return `${require_dist.getFrontendUrl(baseUrl, frontendPort)}/project/${projectId}/evaluations/${evaluationId}`;
|
|
7267
7274
|
};
|
|
@@ -7358,7 +7365,7 @@ var Evaluation = class {
|
|
|
7358
7365
|
this.name = name;
|
|
7359
7366
|
if (config) {
|
|
7360
7367
|
if (config.concurrencyLimit !== void 0 && config.concurrencyLimit < 1) {
|
|
7361
|
-
logger$
|
|
7368
|
+
logger$3.warn(`concurrencyLimit must be greater than 0. Setting to default of ${DEFAULT_CONCURRENCY}`);
|
|
7362
7369
|
this.concurrencyLimit = DEFAULT_CONCURRENCY;
|
|
7363
7370
|
} else this.concurrencyLimit = config.concurrencyLimit ?? DEFAULT_CONCURRENCY;
|
|
7364
7371
|
this.traceDisableBatch = config.traceDisableBatch ?? false;
|
|
@@ -7370,7 +7377,7 @@ var Evaluation = class {
|
|
|
7370
7377
|
baseUrl: Laminar.getHttpUrl(),
|
|
7371
7378
|
projectApiKey: Laminar.getProjectApiKey()
|
|
7372
7379
|
});
|
|
7373
|
-
if (config?.projectApiKey && config.projectApiKey !== Laminar.getProjectApiKey()) logger$
|
|
7380
|
+
if (config?.projectApiKey && config.projectApiKey !== Laminar.getProjectApiKey()) logger$3.warn("Laminar was already initialized with a different project API key. Ignoring the project API key from the evaluation config.");
|
|
7374
7381
|
return;
|
|
7375
7382
|
}
|
|
7376
7383
|
const key = config?.projectApiKey ?? process.env.LMNR_PROJECT_API_KEY;
|
|
@@ -7403,9 +7410,9 @@ var Evaluation = class {
|
|
|
7403
7410
|
if (source && !source.id) try {
|
|
7404
7411
|
const datasets = await this.client.datasets.getDatasetByName(source.name);
|
|
7405
7412
|
if (datasets.length > 0) source.id = datasets[0].id;
|
|
7406
|
-
else logger$
|
|
7413
|
+
else logger$3.warn(`Dataset ${source.name} not found`);
|
|
7407
7414
|
} catch (error) {
|
|
7408
|
-
logger$
|
|
7415
|
+
logger$3.warn(`Error getting dataset ${source.name}: ` + require_dist.errorMessage(error));
|
|
7409
7416
|
}
|
|
7410
7417
|
}
|
|
7411
7418
|
let resultDatapoints;
|
|
@@ -7604,6 +7611,529 @@ async function evaluate({ data, executor, evaluators, groupName, name, metadata,
|
|
|
7604
7611
|
else return await evaluation.run();
|
|
7605
7612
|
}
|
|
7606
7613
|
//#endregion
|
|
7614
|
+
//#region src/integrations/eve.ts
|
|
7615
|
+
const logger$2 = require_dist.initializeLogger();
|
|
7616
|
+
const EVE_REPORTER_TRACER_NAME = "@lmnr-ai/lmnr/eve-reporter";
|
|
7617
|
+
const EVE_CLIENT_MODULE = "eve/client";
|
|
7618
|
+
const TRACEPARENT_HEADER$1 = "traceparent";
|
|
7619
|
+
/** Same wire name the Temporal instrumentation uses (`temporal/consts.ts`). */
|
|
7620
|
+
const LAMINAR_SPAN_CONTEXT_HEADER$1 = "x-lmnr-span-context";
|
|
7621
|
+
/**
|
|
7622
|
+
* Root span name for every propagated eval, and it never changes. eve calls
|
|
7623
|
+
* `ClientSession.send` before any hook that knows which eval is in flight, and
|
|
7624
|
+
* eve exposes no `onEvalStart`, so the id simply is not knowable here. Renaming
|
|
7625
|
+
* the span later would invalidate the `lmnr.span.path` the processor already
|
|
7626
|
+
* stamped on it and on every descendant, and would make the path we propagate
|
|
7627
|
+
* to the agent stale. The eval id rides on `lmnr.eve.eval.id`, on the trace
|
|
7628
|
+
* metadata, and on the datapoint instead.
|
|
7629
|
+
*/
|
|
7630
|
+
const ROOT_SPAN_NAME = "eve eval";
|
|
7631
|
+
const EXECUTOR_SPAN_NAME = "executor";
|
|
7632
|
+
/** Prototypes already patched — `send` must never be wrapped twice. */
|
|
7633
|
+
const patchedSendPrototypes = /* @__PURE__ */ new WeakSet();
|
|
7634
|
+
/**
|
|
7635
|
+
* Per-eve-client-session state. Keyed off the `ClientSession` instance rather
|
|
7636
|
+
* than an AsyncLocalStorage frame or a "current eval" global: eve runs up to
|
|
7637
|
+
* `maxConcurrency` evals at once, and each eval builds its own `ClientSession`
|
|
7638
|
+
* (`EvalSessionManager` calls `client.session()` per `EvalSessionDriver`), so
|
|
7639
|
+
* the instance is the only correct correlation key available inside `send`.
|
|
7640
|
+
*/
|
|
7641
|
+
const traceByClientSession = /* @__PURE__ */ new WeakMap();
|
|
7642
|
+
/** eve session id -> trace, read by `onEvalComplete` via `result.sessionId`. */
|
|
7643
|
+
const traceByEveSessionId = /* @__PURE__ */ new Map();
|
|
7644
|
+
/** Set by the running reporter's `onRunStart`; cleared by `onRunComplete`. */
|
|
7645
|
+
let activeSessionTraceFactory = null;
|
|
7646
|
+
/** Mirrors eve's own `normalizeSendTurnInput`, then merges the trace headers. */
|
|
7647
|
+
const withTraceHeaders = (input, headers) => {
|
|
7648
|
+
const payload = typeof input === "string" ? { message: input } : { ...input };
|
|
7649
|
+
payload.headers = {
|
|
7650
|
+
...payload.headers ?? {},
|
|
7651
|
+
...headers
|
|
7652
|
+
};
|
|
7653
|
+
return payload;
|
|
7654
|
+
};
|
|
7655
|
+
const openSessionTrace = (clientSession) => {
|
|
7656
|
+
try {
|
|
7657
|
+
const existing = traceByClientSession.get(clientSession);
|
|
7658
|
+
if (existing) return existing;
|
|
7659
|
+
const minted = activeSessionTraceFactory?.();
|
|
7660
|
+
if (minted) traceByClientSession.set(clientSession, minted);
|
|
7661
|
+
return minted;
|
|
7662
|
+
} catch (error) {
|
|
7663
|
+
logger$2.warn(`Laminar eve reporter: failed to open a session trace: ` + require_dist.errorMessage(error));
|
|
7664
|
+
return;
|
|
7665
|
+
}
|
|
7666
|
+
};
|
|
7667
|
+
/**
|
|
7668
|
+
* eve assigns the session id on the POST that `send` awaits, so the returned
|
|
7669
|
+
* `MessageResponse` is the earliest place the runner can bind the eve session
|
|
7670
|
+
* id to the trace it minted.
|
|
7671
|
+
*/
|
|
7672
|
+
const recordEveSessionId = (response, sessionTrace) => {
|
|
7673
|
+
const sessionId = response?.sessionId;
|
|
7674
|
+
if (typeof sessionId !== "string" || sessionId.length === 0) return;
|
|
7675
|
+
sessionTrace.sessionIds.add(sessionId);
|
|
7676
|
+
traceByEveSessionId.set(sessionId, sessionTrace);
|
|
7677
|
+
};
|
|
7678
|
+
/**
|
|
7679
|
+
* Build the propagation headers for the EXECUTOR span. Plain HTTP strings — eve
|
|
7680
|
+
* forwards `SendTurnPayload.headers` verbatim to `fetch`.
|
|
7681
|
+
*
|
|
7682
|
+
* The Laminar context carries the full path. Laminar nests spans by
|
|
7683
|
+
* `lmnr.span.ids_path`, not by OTel `parentSpanId`, so a receiver that adopts
|
|
7684
|
+
* only the ids lands its spans as a second root on our trace. The path is what
|
|
7685
|
+
* makes the agent's subtree render UNDER the executor. Both paths are constants
|
|
7686
|
+
* here — neither the root nor the executor span is ever renamed.
|
|
7687
|
+
*/
|
|
7688
|
+
const buildTraceHeaders = (rootSpan, executorSpan) => {
|
|
7689
|
+
const spanContext = executorSpan.spanContext();
|
|
7690
|
+
const laminarContext = {
|
|
7691
|
+
traceId: require_dist.otelTraceIdToUUID(spanContext.traceId),
|
|
7692
|
+
spanId: require_dist.otelSpanIdToUUID(spanContext.spanId),
|
|
7693
|
+
isRemote: true,
|
|
7694
|
+
spanPath: [ROOT_SPAN_NAME, EXECUTOR_SPAN_NAME],
|
|
7695
|
+
spanIdsPath: [require_dist.otelSpanIdToUUID(rootSpan.spanContext().spanId), require_dist.otelSpanIdToUUID(spanContext.spanId)]
|
|
7696
|
+
};
|
|
7697
|
+
return {
|
|
7698
|
+
[TRACEPARENT_HEADER$1]: `00-${spanContext.traceId}-${spanContext.spanId}-01`,
|
|
7699
|
+
[LAMINAR_SPAN_CONTEXT_HEADER$1]: JSON.stringify(laminarContext)
|
|
7700
|
+
};
|
|
7701
|
+
};
|
|
7702
|
+
/**
|
|
7703
|
+
* Bind this session's ROOT span into the calling eval's async context, so work
|
|
7704
|
+
* the eval does in the RUNNER process after `send` resolves lands on this trace
|
|
7705
|
+
* instead of opening its own. The concrete case is `t.judge.autoevals.*`: eve
|
|
7706
|
+
* runs the judge's model call in the runner, and Laminar's AI SDK integration
|
|
7707
|
+
* parents it to `LaminarContextManager.getContext()`.
|
|
7708
|
+
*
|
|
7709
|
+
* The root — not a pre-opened judge span — is the binding target on purpose.
|
|
7710
|
+
* An eval may record any number of judge assertions, and each one runs its own
|
|
7711
|
+
* model call. Binding the root gives every judge its own child of the root; a
|
|
7712
|
+
* single pre-opened parent would collect all of them under whichever judge
|
|
7713
|
+
* happened to run first.
|
|
7714
|
+
*
|
|
7715
|
+
* `pushContext` uses `AsyncLocalStorage.enterWith`, so this MUST run
|
|
7716
|
+
* synchronously before `send`'s first `await` — at that point we are still
|
|
7717
|
+
* executing in the caller's async context, so the store we set is the one
|
|
7718
|
+
* `test(t)` continues with. Each eval's `test(t)` runs in its own async chain,
|
|
7719
|
+
* so concurrent evals never see each other's root span; do NOT replace this
|
|
7720
|
+
* with the process-global context stack, which would cross-attribute.
|
|
7721
|
+
*
|
|
7722
|
+
* Judge spans reach Laminar only when the runner opts in — `Laminar.initialize()`
|
|
7723
|
+
* plus a globally registered AI SDK telemetry integration. Without that the
|
|
7724
|
+
* binding is inert, never wrong.
|
|
7725
|
+
*
|
|
7726
|
+
* Never popped: the store dies with the eval's async chain.
|
|
7727
|
+
*/
|
|
7728
|
+
const bindEvalContext = (sessionTrace) => {
|
|
7729
|
+
try {
|
|
7730
|
+
LaminarContextManager.pushContext(_opentelemetry_api.trace.setSpan(_opentelemetry_api.ROOT_CONTEXT, sessionTrace.rootSpan));
|
|
7731
|
+
} catch (error) {
|
|
7732
|
+
logger$2.warn(`Laminar eve reporter: failed to bind the eval context: ` + require_dist.errorMessage(error));
|
|
7733
|
+
}
|
|
7734
|
+
};
|
|
7735
|
+
/**
|
|
7736
|
+
* Wrap `ClientSession.prototype.send` so every eve turn carries the trace
|
|
7737
|
+
* context of a runner-minted Laminar span. Idempotent per prototype.
|
|
7738
|
+
*
|
|
7739
|
+
* @internal Exported for tests, which drive it with a stub class so the suite
|
|
7740
|
+
* keeps no dependency on eve.
|
|
7741
|
+
*/
|
|
7742
|
+
const patchEveClientSession = (sessionClass) => {
|
|
7743
|
+
const prototype = sessionClass?.prototype;
|
|
7744
|
+
const original = prototype?.send;
|
|
7745
|
+
if (!prototype || typeof original !== "function") return false;
|
|
7746
|
+
if (patchedSendPrototypes.has(prototype)) return true;
|
|
7747
|
+
prototype.send = async function(input) {
|
|
7748
|
+
const sessionTrace = openSessionTrace(this);
|
|
7749
|
+
if (!sessionTrace) return original.call(this, input);
|
|
7750
|
+
bindEvalContext(sessionTrace);
|
|
7751
|
+
const response = await original.call(this, withTraceHeaders(input, sessionTrace.headers));
|
|
7752
|
+
try {
|
|
7753
|
+
recordEveSessionId(response, sessionTrace);
|
|
7754
|
+
} catch (error) {
|
|
7755
|
+
logger$2.warn(`Laminar eve reporter: failed to record the eve session id: ` + require_dist.errorMessage(error));
|
|
7756
|
+
}
|
|
7757
|
+
return response;
|
|
7758
|
+
};
|
|
7759
|
+
patchedSendPrototypes.add(prototype);
|
|
7760
|
+
return true;
|
|
7761
|
+
};
|
|
7762
|
+
/**
|
|
7763
|
+
* Load eve's `ClientSession` without depending on eve. Mirrors the guarded
|
|
7764
|
+
* dynamic import in eve's own Braintrust reporter (`loadBraintrustSdk`), except
|
|
7765
|
+
* a missing eve degrades instead of throwing — the reporter must keep working
|
|
7766
|
+
* when it is registered outside an eve run.
|
|
7767
|
+
*/
|
|
7768
|
+
const loadEveClientSession = async () => {
|
|
7769
|
+
try {
|
|
7770
|
+
const sessionClass = (await import(EVE_CLIENT_MODULE)).ClientSession;
|
|
7771
|
+
return typeof sessionClass === "function" ? sessionClass : void 0;
|
|
7772
|
+
} catch {
|
|
7773
|
+
return;
|
|
7774
|
+
}
|
|
7775
|
+
};
|
|
7776
|
+
const didAssertionPass = (assertion) => {
|
|
7777
|
+
if (typeof assertion.passed === "boolean") return assertion.passed;
|
|
7778
|
+
if (typeof assertion.score === "number") {
|
|
7779
|
+
if (typeof assertion.threshold === "number") return assertion.score >= assertion.threshold;
|
|
7780
|
+
if (assertion.severity === "gate") return assertion.score > 0;
|
|
7781
|
+
}
|
|
7782
|
+
return true;
|
|
7783
|
+
};
|
|
7784
|
+
/**
|
|
7785
|
+
* Keep Laminar's top-level score columns stable across heterogeneous eve evals.
|
|
7786
|
+
* Detailed assertion outcomes live in metadata; sparse per-assertion score keys
|
|
7787
|
+
* make Laminar's eval UI look incomplete when different eval files assert
|
|
7788
|
+
* different things.
|
|
7789
|
+
*/
|
|
7790
|
+
const resultToScores = (result) => {
|
|
7791
|
+
const assertions = result.assertions ?? [];
|
|
7792
|
+
const gateAssertions = assertions.filter((assertion) => assertion.severity === "gate");
|
|
7793
|
+
const thresholdedSoftAssertions = assertions.filter((assertion) => assertion.severity === "soft" && typeof assertion.threshold === "number");
|
|
7794
|
+
return {
|
|
7795
|
+
"eve.verdict.passed": result.verdict === "passed" ? 1 : 0,
|
|
7796
|
+
"eve.gates.passed": gateAssertions.every(didAssertionPass) ? 1 : 0,
|
|
7797
|
+
"eve.soft_thresholds.passed": thresholdedSoftAssertions.every(didAssertionPass) ? 1 : 0
|
|
7798
|
+
};
|
|
7799
|
+
};
|
|
7800
|
+
const assertionsMetadata = (assertions) => assertions.map((assertion) => ({
|
|
7801
|
+
name: assertion.name,
|
|
7802
|
+
score: assertion.score,
|
|
7803
|
+
severity: assertion.severity,
|
|
7804
|
+
threshold: assertion.threshold,
|
|
7805
|
+
passed: assertion.passed,
|
|
7806
|
+
message: assertion.message,
|
|
7807
|
+
metadata: assertion.metadata
|
|
7808
|
+
}));
|
|
7809
|
+
/** Surface failed assertions in metadata so a failing run is debuggable. */
|
|
7810
|
+
const failedAssertionsMetadata = (assertions) => {
|
|
7811
|
+
const failed = assertions.filter((assertion) => !didAssertionPass(assertion)).map((assertion) => ({
|
|
7812
|
+
name: assertion.name,
|
|
7813
|
+
message: assertion.message
|
|
7814
|
+
}));
|
|
7815
|
+
return failed.length > 0 ? { failedAssertions: failed } : {};
|
|
7816
|
+
};
|
|
7817
|
+
const traceIdFromSpan = (span) => require_dist.otelTraceIdToUUID(span.spanContext().traceId);
|
|
7818
|
+
/**
|
|
7819
|
+
* A Laminar reporter for eve evals. Register it globally in `evals.config.ts`
|
|
7820
|
+
* or per-eval via the `reporters` field — eve runs and grades each eval, then
|
|
7821
|
+
* hands the graded result here, and this reporter ships it to Laminar as an
|
|
7822
|
+
* evaluation run with one datapoint per eval.
|
|
7823
|
+
*
|
|
7824
|
+
* The datapoint's trace id is never looked up — the reporter OWNS the trace.
|
|
7825
|
+
* `patchEveClientSession` wraps eve's `ClientSession.send` and mints the
|
|
7826
|
+
* EVALUATION root + EXECUTOR child on the first turn of each session, so the
|
|
7827
|
+
* runner already knows the trace id and pushes it to the agent as a
|
|
7828
|
+
* `traceparent` header. The eve session id is only the in-process key that ties
|
|
7829
|
+
* the send we instrumented to the graded result eve hands back later.
|
|
7830
|
+
*
|
|
7831
|
+
* Two outcomes, recorded on `metadata.traceResolution`:
|
|
7832
|
+
*
|
|
7833
|
+
* 1. `"propagated"` — the normal path, above. The agent joins the trace only
|
|
7834
|
+
* when `agent/instrumentation.ts` sets `traceChannelRequests: true` and the
|
|
7835
|
+
* agent process runs with `WORKFLOW_TRACE_MODE=continuous`.
|
|
7836
|
+
* 2. `"reporter-fallback"` — no session trace was minted (propagation disabled,
|
|
7837
|
+
* or eve produced no session id). The reporter opens its own EVALUATION span
|
|
7838
|
+
* so the grade still lands somewhere debuggable; it holds no agent work.
|
|
7839
|
+
*
|
|
7840
|
+
* `t.judge.autoevals.*` model calls run in the RUNNER process, and they reach
|
|
7841
|
+
* Laminar only when the runner registers an AI SDK telemetry integration. eve
|
|
7842
|
+
* imports `generateText` inside its own bundle, so `wrapAISDK` cannot reach it —
|
|
7843
|
+
* but AI SDK v7 reads registered integrations off `globalThis`, which does. One
|
|
7844
|
+
* line in `evals.config.ts`:
|
|
7845
|
+
*
|
|
7846
|
+
* ```ts
|
|
7847
|
+
* registerTelemetry(new LaminarAiSdkTelemetry());
|
|
7848
|
+
* ```
|
|
7849
|
+
*
|
|
7850
|
+
* Judge spans and eve eval spans then share ONE tracer provider — whichever of
|
|
7851
|
+
* the two initialized Laminar first (see {@link LaminarReporter.ensureTracing}).
|
|
7852
|
+
* Each judge gets its own span under the eval's root — see
|
|
7853
|
+
* {@link bindEvalContext}, and {@link LaminarReporter.flush} for how spans ship.
|
|
7854
|
+
* Without that line the reporter still records every assertion's score as an
|
|
7855
|
+
* EVALUATOR span; only the model call is missing.
|
|
7856
|
+
*
|
|
7857
|
+
* @example
|
|
7858
|
+
* ```ts
|
|
7859
|
+
* import { defineEvalConfig } from "eve/evals";
|
|
7860
|
+
* import { LaminarReporter } from "@lmnr-ai/lmnr";
|
|
7861
|
+
*
|
|
7862
|
+
* export default defineEvalConfig({
|
|
7863
|
+
* reporters: [new LaminarReporter({ name: "weather-agent" })],
|
|
7864
|
+
* });
|
|
7865
|
+
* ```
|
|
7866
|
+
*/
|
|
7867
|
+
var LaminarReporter = class {
|
|
7868
|
+
constructor(options = {}) {
|
|
7869
|
+
this.evalsById = /* @__PURE__ */ new Map();
|
|
7870
|
+
this.index = 0;
|
|
7871
|
+
this.openSessionTraces = /* @__PURE__ */ new Set();
|
|
7872
|
+
this.sessionTraceFactory = () => this.mintSessionTrace();
|
|
7873
|
+
this.options = options;
|
|
7874
|
+
}
|
|
7875
|
+
async onRunStart(evaluations, target) {
|
|
7876
|
+
this.evalId = void 0;
|
|
7877
|
+
this.evalsById = new Map(evaluations.filter((evaluation) => typeof evaluation.id === "string").map((evaluation) => [evaluation.id, evaluation]));
|
|
7878
|
+
this.index = 0;
|
|
7879
|
+
this.finishOpenSessionTraces();
|
|
7880
|
+
try {
|
|
7881
|
+
this.client = this.options.client ?? new require_dist.LaminarClient({
|
|
7882
|
+
baseUrl: this.options.baseUrl,
|
|
7883
|
+
projectApiKey: this.options.projectApiKey
|
|
7884
|
+
});
|
|
7885
|
+
this.ensureTracing();
|
|
7886
|
+
if (this.options.propagateTraceContext !== false) {
|
|
7887
|
+
activeSessionTraceFactory = this.sessionTraceFactory;
|
|
7888
|
+
patchEveClientSession(await loadEveClientSession());
|
|
7889
|
+
}
|
|
7890
|
+
const evaluation = await this.client.evals.init(this.options.name, this.options.groupName, {
|
|
7891
|
+
...this.options.metadata ?? {},
|
|
7892
|
+
source: "eve",
|
|
7893
|
+
targetKind: target?.kind,
|
|
7894
|
+
targetUrl: target?.url,
|
|
7895
|
+
evalCount: evaluations.length
|
|
7896
|
+
});
|
|
7897
|
+
this.evalId = evaluation.id;
|
|
7898
|
+
const url = require_dist.getFrontendUrl(this.client.configuredBaseUrl ?? this.options.baseUrl) + `/project/${evaluation.projectId}/evaluations/${evaluation.id}`;
|
|
7899
|
+
process.stdout.write(`\nLaminar: check eve eval results at ${url}\n`);
|
|
7900
|
+
} catch (error) {
|
|
7901
|
+
logger$2.error(`Laminar eve reporter: failed to start run: ${require_dist.errorMessage(error)}`);
|
|
7902
|
+
if (!this.evalId) {
|
|
7903
|
+
this.client = void 0;
|
|
7904
|
+
if (activeSessionTraceFactory === this.sessionTraceFactory) activeSessionTraceFactory = null;
|
|
7905
|
+
}
|
|
7906
|
+
}
|
|
7907
|
+
}
|
|
7908
|
+
async onEvalComplete(result) {
|
|
7909
|
+
const client = this.client;
|
|
7910
|
+
const evalId = this.evalId;
|
|
7911
|
+
if (!client || !evalId) return;
|
|
7912
|
+
const index = this.index++;
|
|
7913
|
+
const task = result.result ?? {};
|
|
7914
|
+
const derived = task.derived ?? {};
|
|
7915
|
+
const assertions = result.assertions ?? [];
|
|
7916
|
+
const evalDescription = (typeof result.id === "string" ? this.evalsById.get(result.id) : void 0)?.description;
|
|
7917
|
+
const traceResolution = this.resolveDatapointTrace({
|
|
7918
|
+
evalId: result.id ?? String(index),
|
|
7919
|
+
description: evalDescription,
|
|
7920
|
+
verdict: result.verdict,
|
|
7921
|
+
sessionId: task.sessionId
|
|
7922
|
+
});
|
|
7923
|
+
try {
|
|
7924
|
+
const datapointId = await client.evals.createDatapoint({
|
|
7925
|
+
evalId,
|
|
7926
|
+
data: result.id ?? null,
|
|
7927
|
+
target: task.finalMessage ?? null,
|
|
7928
|
+
index,
|
|
7929
|
+
traceId: traceResolution.traceId,
|
|
7930
|
+
metadata: {
|
|
7931
|
+
name: result.id,
|
|
7932
|
+
verdict: result.verdict,
|
|
7933
|
+
status: task.status,
|
|
7934
|
+
description: evalDescription,
|
|
7935
|
+
sessionId: task.sessionId,
|
|
7936
|
+
traceResolution: traceResolution.source,
|
|
7937
|
+
skipReason: result.skipReason,
|
|
7938
|
+
error: result.error,
|
|
7939
|
+
toolCalls: (derived.toolCalls ?? []).map((call) => call.name).filter((name) => typeof name === "string"),
|
|
7940
|
+
toolCallCount: derived.toolCallCount,
|
|
7941
|
+
parked: derived.parked,
|
|
7942
|
+
failureCode: derived.failureCode,
|
|
7943
|
+
modelId: task.runtimeIdentity?.modelId,
|
|
7944
|
+
assertions: assertionsMetadata(assertions),
|
|
7945
|
+
...failedAssertionsMetadata(assertions)
|
|
7946
|
+
}
|
|
7947
|
+
});
|
|
7948
|
+
const executorOutput = task.output ?? task.finalMessage ?? null;
|
|
7949
|
+
await client.evals.updateDatapoint({
|
|
7950
|
+
evalId,
|
|
7951
|
+
datapointId,
|
|
7952
|
+
scores: resultToScores(result),
|
|
7953
|
+
executorOutput
|
|
7954
|
+
});
|
|
7955
|
+
} catch (error) {
|
|
7956
|
+
if (traceResolution.source === "reporter-fallback") traceResolution.span.recordException(error);
|
|
7957
|
+
logger$2.error(`Laminar eve reporter: failed to report eval "${result.id ?? index}": ${require_dist.errorMessage(error)}`);
|
|
7958
|
+
} finally {
|
|
7959
|
+
if (traceResolution.source === "reporter-fallback") traceResolution.span.end();
|
|
7960
|
+
if (traceResolution.source === "propagated") this.finishSessionTrace(traceResolution.sessionTrace, {
|
|
7961
|
+
evalId: result.id,
|
|
7962
|
+
description: evalDescription,
|
|
7963
|
+
verdict: result.verdict,
|
|
7964
|
+
status: task.status,
|
|
7965
|
+
output: task.output ?? task.finalMessage ?? null,
|
|
7966
|
+
assertions
|
|
7967
|
+
});
|
|
7968
|
+
await this.flush();
|
|
7969
|
+
}
|
|
7970
|
+
}
|
|
7971
|
+
async onRunComplete() {
|
|
7972
|
+
this.finishOpenSessionTraces();
|
|
7973
|
+
if (activeSessionTraceFactory === this.sessionTraceFactory) activeSessionTraceFactory = null;
|
|
7974
|
+
await this.flush();
|
|
7975
|
+
this.evalId = void 0;
|
|
7976
|
+
this.evalsById.clear();
|
|
7977
|
+
}
|
|
7978
|
+
/**
|
|
7979
|
+
* Point the process's Laminar tracing at this reporter's project, unless
|
|
7980
|
+
* something already initialized it. Mirrors `LaminarAiSdkTelemetry`, which
|
|
7981
|
+
* initializes the same way for judge spans — so eve eval spans and judge
|
|
7982
|
+
* spans share ONE tracer provider however the run was set up. Without this,
|
|
7983
|
+
* `getTracer()` returns a noop whenever nobody registered the AI SDK
|
|
7984
|
+
* integration, and every eve span would be dropped silently.
|
|
7985
|
+
*/
|
|
7986
|
+
ensureTracing() {
|
|
7987
|
+
if (Laminar.initialized()) {
|
|
7988
|
+
const ourKey = this.client?.apiKey ?? this.options.projectApiKey;
|
|
7989
|
+
const tracingKey = getConfiguredApiKey();
|
|
7990
|
+
if (ourKey && tracingKey && ourKey !== tracingKey) logger$2.warn("Laminar eve reporter: Laminar is already initialized with a different project API key. eve eval spans go to that project while datapoints go to the reporter's, so datapoint trace ids will not resolve. Point both at the same project.");
|
|
7991
|
+
return;
|
|
7992
|
+
}
|
|
7993
|
+
Laminar.initialize({
|
|
7994
|
+
projectApiKey: this.client?.apiKey ?? this.options.projectApiKey,
|
|
7995
|
+
baseUrl: this.client?.configuredBaseUrl ?? this.options.baseUrl,
|
|
7996
|
+
spanProcessor: this.options.spanProcessor,
|
|
7997
|
+
instrumentModules: {},
|
|
7998
|
+
disableBatch: true
|
|
7999
|
+
});
|
|
8000
|
+
}
|
|
8001
|
+
/**
|
|
8002
|
+
* Flush the process's Laminar pipeline — eve eval spans AND judge spans, which
|
|
8003
|
+
* now share one provider. eve ends `eve eval` with `process.exit()` (skipping
|
|
8004
|
+
* `beforeExit`), so these calls are the only points at which spans ship.
|
|
8005
|
+
* Never `shutdown()`: the pipeline may belong to the host, not to us.
|
|
8006
|
+
*/
|
|
8007
|
+
async flush() {
|
|
8008
|
+
try {
|
|
8009
|
+
await Laminar.flush();
|
|
8010
|
+
} catch (error) {
|
|
8011
|
+
logger$2.warn(`Laminar eve reporter: failed to flush spans: ` + require_dist.errorMessage(error));
|
|
8012
|
+
}
|
|
8013
|
+
}
|
|
8014
|
+
/**
|
|
8015
|
+
* Open the eval's Laminar spans for one eve client session: an EVALUATION
|
|
8016
|
+
* root plus the EXECUTOR child the agent's turn is parented to. Called from
|
|
8017
|
+
* the patched `send`, so it must never throw into the user's eval.
|
|
8018
|
+
*/
|
|
8019
|
+
mintSessionTrace() {
|
|
8020
|
+
const tracer = getTracer();
|
|
8021
|
+
const rootSpan = tracer.startSpan(ROOT_SPAN_NAME, { attributes: {
|
|
8022
|
+
[require_dist.SPAN_TYPE]: "EVALUATION",
|
|
8023
|
+
[require_dist.TRACE_TYPE]: "EVALUATION",
|
|
8024
|
+
"lmnr.eve.reporter": EVE_REPORTER_TRACER_NAME
|
|
8025
|
+
} }, _opentelemetry_api.ROOT_CONTEXT);
|
|
8026
|
+
const executorSpan = tracer.startSpan(EXECUTOR_SPAN_NAME, { attributes: {
|
|
8027
|
+
[require_dist.SPAN_TYPE]: "EXECUTOR",
|
|
8028
|
+
[require_dist.TRACE_TYPE]: "EVALUATION"
|
|
8029
|
+
} }, _opentelemetry_api.trace.setSpan(_opentelemetry_api.ROOT_CONTEXT, rootSpan));
|
|
8030
|
+
const sessionTrace = {
|
|
8031
|
+
traceId: require_dist.otelTraceIdToUUID(rootSpan.spanContext().traceId),
|
|
8032
|
+
rootSpan,
|
|
8033
|
+
executorSpan,
|
|
8034
|
+
tracer,
|
|
8035
|
+
headers: buildTraceHeaders(rootSpan, executorSpan),
|
|
8036
|
+
sessionIds: /* @__PURE__ */ new Set(),
|
|
8037
|
+
ended: false
|
|
8038
|
+
};
|
|
8039
|
+
this.openSessionTraces.add(sessionTrace);
|
|
8040
|
+
return sessionTrace;
|
|
8041
|
+
}
|
|
8042
|
+
/** Grade, close and release one session trace. Idempotent. */
|
|
8043
|
+
finishSessionTrace(sessionTrace, grade) {
|
|
8044
|
+
if (sessionTrace.ended) return;
|
|
8045
|
+
sessionTrace.ended = true;
|
|
8046
|
+
this.openSessionTraces.delete(sessionTrace);
|
|
8047
|
+
for (const sessionId of sessionTrace.sessionIds) traceByEveSessionId.delete(sessionId);
|
|
8048
|
+
try {
|
|
8049
|
+
sessionTrace.rootSpan.setAttributes({
|
|
8050
|
+
"lmnr.eve.eval.id": grade.evalId ?? "",
|
|
8051
|
+
"lmnr.eve.eval.verdict": grade.verdict ?? "",
|
|
8052
|
+
"lmnr.eve.eval.status": grade.status ?? "",
|
|
8053
|
+
[require_dist.SPAN_INPUT]: JSON.stringify({
|
|
8054
|
+
evalId: grade.evalId,
|
|
8055
|
+
description: grade.description
|
|
8056
|
+
}),
|
|
8057
|
+
[require_dist.SPAN_OUTPUT]: JSON.stringify(grade.output ?? null),
|
|
8058
|
+
...require_dist.metadataToAttributes({
|
|
8059
|
+
source: "eve",
|
|
8060
|
+
eveEvalId: grade.evalId ?? "",
|
|
8061
|
+
eveEvalDescription: grade.description ?? "",
|
|
8062
|
+
eveEvalVerdict: grade.verdict ?? "",
|
|
8063
|
+
eveSessionId: [...sessionTrace.sessionIds].join(",")
|
|
8064
|
+
})
|
|
8065
|
+
});
|
|
8066
|
+
sessionTrace.executorSpan.setAttribute(require_dist.SPAN_OUTPUT, JSON.stringify(grade.output ?? null));
|
|
8067
|
+
this.recordEvaluatorSpans(sessionTrace, grade.assertions ?? []);
|
|
8068
|
+
sessionTrace.executorSpan.end();
|
|
8069
|
+
sessionTrace.rootSpan.end();
|
|
8070
|
+
} catch (error) {
|
|
8071
|
+
logger$2.warn(`Laminar eve reporter: failed to finish the session trace: ` + require_dist.errorMessage(error));
|
|
8072
|
+
}
|
|
8073
|
+
}
|
|
8074
|
+
/**
|
|
8075
|
+
* One EVALUATOR span per eve assertion, judge or not. They are created at
|
|
8076
|
+
* grade time (the assertions only exist then) as short children of the
|
|
8077
|
+
* still-open root. No explicit parent path is needed: the root keeps the name
|
|
8078
|
+
* it was minted with, so the processor's cached path for it is still correct.
|
|
8079
|
+
*/
|
|
8080
|
+
recordEvaluatorSpans(sessionTrace, assertions) {
|
|
8081
|
+
const rootContext = _opentelemetry_api.trace.setSpan(_opentelemetry_api.ROOT_CONTEXT, sessionTrace.rootSpan);
|
|
8082
|
+
for (const assertion of assertions) {
|
|
8083
|
+
const name = assertion.name ?? "assertion";
|
|
8084
|
+
const output = JSON.stringify({
|
|
8085
|
+
score: assertion.score ?? null,
|
|
8086
|
+
passed: didAssertionPass(assertion),
|
|
8087
|
+
severity: assertion.severity,
|
|
8088
|
+
threshold: assertion.threshold,
|
|
8089
|
+
message: assertion.message
|
|
8090
|
+
});
|
|
8091
|
+
sessionTrace.tracer.startSpan(name, { attributes: {
|
|
8092
|
+
[require_dist.SPAN_TYPE]: "EVALUATOR",
|
|
8093
|
+
[require_dist.TRACE_TYPE]: "EVALUATION",
|
|
8094
|
+
[require_dist.SPAN_OUTPUT]: output
|
|
8095
|
+
} }, rootContext).end();
|
|
8096
|
+
}
|
|
8097
|
+
}
|
|
8098
|
+
finishOpenSessionTraces() {
|
|
8099
|
+
for (const sessionTrace of [...this.openSessionTraces]) this.finishSessionTrace(sessionTrace, {});
|
|
8100
|
+
}
|
|
8101
|
+
/**
|
|
8102
|
+
* Resolve the trace this datapoint links to. There is no lookup: either
|
|
8103
|
+
* `patchEveClientSession` already minted the session's trace (and we know its
|
|
8104
|
+
* id), or we open a reporter-owned EVALUATION span to hold the grade.
|
|
8105
|
+
*/
|
|
8106
|
+
resolveDatapointTrace({ evalId, description, verdict, sessionId }) {
|
|
8107
|
+
const sessionTrace = sessionId ? traceByEveSessionId.get(sessionId) : void 0;
|
|
8108
|
+
if (sessionTrace) return {
|
|
8109
|
+
traceId: sessionTrace.traceId,
|
|
8110
|
+
source: "propagated",
|
|
8111
|
+
sessionTrace
|
|
8112
|
+
};
|
|
8113
|
+
const span = getTracer().startSpan(`eve eval ${evalId}`, { attributes: {
|
|
8114
|
+
[require_dist.SPAN_TYPE]: "EVALUATION",
|
|
8115
|
+
[require_dist.TRACE_TYPE]: "EVALUATION",
|
|
8116
|
+
"lmnr.eve.reporter": EVE_REPORTER_TRACER_NAME,
|
|
8117
|
+
"lmnr.eve.eval.id": evalId,
|
|
8118
|
+
"lmnr.eve.eval.verdict": verdict ?? "",
|
|
8119
|
+
...sessionId ? { "lmnr.eve.session.id": sessionId } : {},
|
|
8120
|
+
"lmnr.eve.trace_resolution": "reporter-fallback",
|
|
8121
|
+
...require_dist.metadataToAttributes({
|
|
8122
|
+
source: "eve",
|
|
8123
|
+
eveEvalId: evalId,
|
|
8124
|
+
eveEvalDescription: description ?? "",
|
|
8125
|
+
eveEvalVerdict: verdict ?? "",
|
|
8126
|
+
eveSessionId: sessionId ?? ""
|
|
8127
|
+
})
|
|
8128
|
+
} }, _opentelemetry_api.ROOT_CONTEXT);
|
|
8129
|
+
return {
|
|
8130
|
+
traceId: traceIdFromSpan(span),
|
|
8131
|
+
source: "reporter-fallback",
|
|
8132
|
+
span
|
|
8133
|
+
};
|
|
8134
|
+
}
|
|
8135
|
+
};
|
|
8136
|
+
//#endregion
|
|
7607
8137
|
//#region src/debug/hash.ts
|
|
7608
8138
|
/**
|
|
7609
8139
|
* Debug-replay input hashing.
|
|
@@ -9486,6 +10016,7 @@ exports.LaminarAiSdkTelemetry = LaminarAiSdkTelemetry;
|
|
|
9486
10016
|
exports.LaminarAttributes = require_dist.LaminarAttributes;
|
|
9487
10017
|
exports.LaminarClient = require_dist.LaminarClient;
|
|
9488
10018
|
exports.LaminarDataset = LaminarDataset;
|
|
10019
|
+
exports.LaminarReporter = LaminarReporter;
|
|
9489
10020
|
exports.LaminarSpanProcessor = LaminarSpanProcessor;
|
|
9490
10021
|
exports.LaminarTemporalActivityClientInterceptor = ActivityClientInterceptor;
|
|
9491
10022
|
exports.LaminarTemporalActivityInterceptorFactory = ActivityInterceptorFactory;
|