@lmnr-ai/lmnr 0.8.52 → 0.8.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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/{evaluations-CgcBhNjN.d.cts → evaluations-BXDpgOzM.d.cts} +26 -3
- package/dist/{evaluations-GnmUSvoK.d.mts → evaluations-BwB2JsRa.d.mts} +26 -3
- package/dist/{file-utils-DaZefKLb.mjs → file-utils-CwqjWMsF.mjs} +2 -2
- package/dist/{file-utils-DaZefKLb.mjs.map → file-utils-CwqjWMsF.mjs.map} +1 -1
- package/dist/{file-utils-C_q3Dsf2.cjs → file-utils-CyBBBeeW.cjs} +2 -2
- package/dist/{file-utils-C_q3Dsf2.cjs.map → file-utils-CyBBBeeW.cjs.map} +1 -1
- package/dist/index.cjs +1374 -201
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -6
- package/dist/index.d.mts +19 -6
- package/dist/index.mjs +1375 -202
- package/dist/index.mjs.map +1 -1
- package/dist/{utils-C6gt-rSg.mjs → utils-DavLzQA8.mjs} +5 -4
- package/dist/{utils-C6gt-rSg.mjs.map → utils-DavLzQA8.mjs.map} +1 -1
- package/dist/{utils-vnm5E0kk.cjs → utils-DcdjJ-4n.cjs} +10 -3
- package/dist/{utils-vnm5E0kk.cjs.map → utils-DcdjJ-4n.cjs.map} +1 -1
- package/package.json +15 -12
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_rolldown_runtime = require("./rolldown-runtime-Ctb5zv51.cjs");
|
|
3
|
-
const require_utils = require("./utils-
|
|
3
|
+
const require_utils = require("./utils-DcdjJ-4n.cjs");
|
|
4
4
|
const require_consts = require("./consts-9rSS0oeR.cjs");
|
|
5
5
|
let path = require("path");
|
|
6
6
|
path = require_rolldown_runtime.__toESM(path);
|
|
@@ -12,7 +12,6 @@ let _opentelemetry_sdk_trace_node = require("@opentelemetry/sdk-trace-node");
|
|
|
12
12
|
let _opentelemetry_semantic_conventions = require("@opentelemetry/semantic-conventions");
|
|
13
13
|
let _traceloop_instrumentation_bedrock = require("@traceloop/instrumentation-bedrock");
|
|
14
14
|
let _traceloop_instrumentation_chromadb = require("@traceloop/instrumentation-chromadb");
|
|
15
|
-
let _traceloop_instrumentation_langchain = require("@traceloop/instrumentation-langchain");
|
|
16
15
|
let _traceloop_instrumentation_pinecone = require("@traceloop/instrumentation-pinecone");
|
|
17
16
|
let _traceloop_instrumentation_qdrant = require("@traceloop/instrumentation-qdrant");
|
|
18
17
|
let _traceloop_instrumentation_together = require("@traceloop/instrumentation-together");
|
|
@@ -29,6 +28,7 @@ os = require_rolldown_runtime.__toESM(os);
|
|
|
29
28
|
let async_hooks = require("async_hooks");
|
|
30
29
|
let zod_to_json_schema = require("zod-to-json-schema");
|
|
31
30
|
let _opentelemetry_core = require("@opentelemetry/core");
|
|
31
|
+
let node_async_hooks = require("node:async_hooks");
|
|
32
32
|
let _grpc_grpc_js = require("@grpc/grpc-js");
|
|
33
33
|
let _opentelemetry_exporter_trace_otlp_grpc = require("@opentelemetry/exporter-trace-otlp-grpc");
|
|
34
34
|
let _opentelemetry_exporter_trace_otlp_proto = require("@opentelemetry/exporter-trace-otlp-proto");
|
|
@@ -195,7 +195,7 @@ var LaminarDataset = class extends EvaluationDataset {
|
|
|
195
195
|
*/
|
|
196
196
|
async push(paths, recursive = false) {
|
|
197
197
|
if (!this.client) throw new Error("Client not set");
|
|
198
|
-
const { loadFromPaths } = await Promise.resolve().then(() => require("./file-utils-
|
|
198
|
+
const { loadFromPaths } = await Promise.resolve().then(() => require("./file-utils-CyBBBeeW.cjs")).then((n) => n.file_utils_exports);
|
|
199
199
|
const data = await loadFromPaths(Array.isArray(paths) ? paths : [paths], recursive);
|
|
200
200
|
if (data.length === 0) {
|
|
201
201
|
console.warn("No data to push. Skipping");
|
|
@@ -211,7 +211,7 @@ var LaminarDataset = class extends EvaluationDataset {
|
|
|
211
211
|
};
|
|
212
212
|
//#endregion
|
|
213
213
|
//#region src/opentelemetry-lib/tracing/compat.ts
|
|
214
|
-
const logger$
|
|
214
|
+
const logger$32 = require_utils.initializeLogger();
|
|
215
215
|
const makeSpanOtelV2Compatible = (span) => {
|
|
216
216
|
const spanAny = span;
|
|
217
217
|
if (spanAny.instrumentationScope && !spanAny.instrumentationLibrary) Object.assign(span, { instrumentationLibrary: spanAny.instrumentationScope });
|
|
@@ -257,7 +257,7 @@ const createResource = (attributes) => {
|
|
|
257
257
|
if (resources.Resource) return new resources.Resource(attributes);
|
|
258
258
|
throw new Error("Unable to create Resource: neither v1 nor v2 API found");
|
|
259
259
|
} catch {
|
|
260
|
-
logger$
|
|
260
|
+
logger$32.debug("Laminar failed to @opentelemetry/resources, continuing without it");
|
|
261
261
|
return;
|
|
262
262
|
}
|
|
263
263
|
};
|
|
@@ -459,7 +459,7 @@ const consumeResponse = async (response) => {
|
|
|
459
459
|
};
|
|
460
460
|
//#endregion
|
|
461
461
|
//#region src/opentelemetry-lib/tracing/stream-utils.ts
|
|
462
|
-
const logger$
|
|
462
|
+
const logger$31 = require_utils.initializeLogger();
|
|
463
463
|
const pendingStreamProcessing = /* @__PURE__ */ new Set();
|
|
464
464
|
/**
|
|
465
465
|
* Wait for all pending stream processing to complete with a timeout
|
|
@@ -467,7 +467,7 @@ const pendingStreamProcessing = /* @__PURE__ */ new Set();
|
|
|
467
467
|
*/
|
|
468
468
|
const waitForPendingStreams = async (timeoutMs = 5e3) => {
|
|
469
469
|
if (pendingStreamProcessing.size === 0) return;
|
|
470
|
-
logger$
|
|
470
|
+
logger$31.debug(`Waiting for ${pendingStreamProcessing.size} pending stream(s)`);
|
|
471
471
|
const initialCount = pendingStreamProcessing.size;
|
|
472
472
|
const pendingPromises = Array.from(pendingStreamProcessing);
|
|
473
473
|
let timedOut = false;
|
|
@@ -478,7 +478,7 @@ const waitForPendingStreams = async (timeoutMs = 5e3) => {
|
|
|
478
478
|
}, timeoutMs);
|
|
479
479
|
});
|
|
480
480
|
await Promise.race([Promise.allSettled(pendingPromises), timeoutPromise]);
|
|
481
|
-
if (timedOut && pendingStreamProcessing.size > 0) logger$
|
|
481
|
+
if (timedOut && pendingStreamProcessing.size > 0) logger$31.warn(`Timeout waiting for ${pendingStreamProcessing.size} pending stream(s) after ${timeoutMs}ms (started with ${initialCount})`);
|
|
482
482
|
};
|
|
483
483
|
/**
|
|
484
484
|
* Track a background promise and ensure cleanup
|
|
@@ -494,34 +494,34 @@ const trackStreamProcessing = (task) => {
|
|
|
494
494
|
* while passing through the original result to the caller
|
|
495
495
|
*/
|
|
496
496
|
const handleStreamResult = (originalResult, streamInfo, span, ignoreOutput, serialize) => {
|
|
497
|
-
logger$
|
|
497
|
+
logger$31.debug(`Handling stream result of type: ${streamInfo.type}`);
|
|
498
498
|
if (streamInfo.type === "aisdk-result") {
|
|
499
499
|
trackStreamProcessing(async () => {
|
|
500
|
-
logger$
|
|
500
|
+
logger$31.debug("Starting background processing for AI SDK result");
|
|
501
501
|
let partialOutput = {};
|
|
502
502
|
try {
|
|
503
503
|
partialOutput = await consumeAISDKResult(streamInfo.result);
|
|
504
504
|
if (shouldSendTraces() && !ignoreOutput) try {
|
|
505
505
|
span.setAttribute(require_utils.SPAN_OUTPUT, serialize(partialOutput));
|
|
506
506
|
} catch (error) {
|
|
507
|
-
logger$
|
|
507
|
+
logger$31.warn("Failed to serialize AI SDK stream output: " + require_utils.errorMessage(error));
|
|
508
508
|
}
|
|
509
509
|
} catch (error) {
|
|
510
510
|
if (Object.keys(partialOutput).length > 0 && shouldSendTraces() && !ignoreOutput) try {
|
|
511
511
|
span.setAttribute(require_utils.SPAN_OUTPUT, serialize(partialOutput));
|
|
512
512
|
} catch (serError) {
|
|
513
|
-
logger$
|
|
513
|
+
logger$31.warn("Failed to serialize partial AI SDK output: " + require_utils.errorMessage(serError));
|
|
514
514
|
}
|
|
515
515
|
span.recordException(error);
|
|
516
516
|
} finally {
|
|
517
|
-
logger$
|
|
517
|
+
logger$31.debug("Ending span for AI SDK result");
|
|
518
518
|
span.end();
|
|
519
519
|
}
|
|
520
520
|
});
|
|
521
521
|
return originalResult;
|
|
522
522
|
}
|
|
523
523
|
if (streamInfo.type === "readable-stream") {
|
|
524
|
-
logger$
|
|
524
|
+
logger$31.debug("Setting up background processing for ReadableStream");
|
|
525
525
|
const { stream, dataPromise } = consumeAndTeeReadableStream(streamInfo.stream);
|
|
526
526
|
trackStreamProcessing(async () => {
|
|
527
527
|
try {
|
|
@@ -533,18 +533,18 @@ const handleStreamResult = (originalResult, streamInfo, span, ignoreOutput, seri
|
|
|
533
533
|
};
|
|
534
534
|
span.setAttribute(require_utils.SPAN_OUTPUT, serialize(output));
|
|
535
535
|
} catch (serError) {
|
|
536
|
-
logger$
|
|
536
|
+
logger$31.warn("Failed to serialize stream output: " + require_utils.errorMessage(serError));
|
|
537
537
|
}
|
|
538
538
|
if (error) span.recordException(error);
|
|
539
539
|
} finally {
|
|
540
|
-
logger$
|
|
540
|
+
logger$31.debug("Ending span for ReadableStream");
|
|
541
541
|
span.end();
|
|
542
542
|
}
|
|
543
543
|
});
|
|
544
544
|
return stream;
|
|
545
545
|
}
|
|
546
546
|
if (streamInfo.type === "async-iterable") {
|
|
547
|
-
logger$
|
|
547
|
+
logger$31.debug("Setting up background processing for AsyncIterable");
|
|
548
548
|
const { iterable, dataPromise } = consumeAndTeeAsyncIterable(streamInfo.iterable);
|
|
549
549
|
trackStreamProcessing(async () => {
|
|
550
550
|
try {
|
|
@@ -556,18 +556,18 @@ const handleStreamResult = (originalResult, streamInfo, span, ignoreOutput, seri
|
|
|
556
556
|
};
|
|
557
557
|
span.setAttribute(require_utils.SPAN_OUTPUT, serialize(output));
|
|
558
558
|
} catch (serError) {
|
|
559
|
-
logger$
|
|
559
|
+
logger$31.warn("Failed to serialize async iterable output: " + require_utils.errorMessage(serError));
|
|
560
560
|
}
|
|
561
561
|
if (error) span.recordException(error);
|
|
562
562
|
} finally {
|
|
563
|
-
logger$
|
|
563
|
+
logger$31.debug("Ending span for AsyncIterable");
|
|
564
564
|
span.end();
|
|
565
565
|
}
|
|
566
566
|
});
|
|
567
567
|
return iterable;
|
|
568
568
|
}
|
|
569
569
|
if (streamInfo.type === "response") {
|
|
570
|
-
logger$
|
|
570
|
+
logger$31.debug("Setting up background processing for Response");
|
|
571
571
|
const originalResponse = streamInfo.response;
|
|
572
572
|
if (!originalResponse.body) {
|
|
573
573
|
span.end();
|
|
@@ -590,19 +590,19 @@ const handleStreamResult = (originalResult, streamInfo, span, ignoreOutput, seri
|
|
|
590
590
|
};
|
|
591
591
|
span.setAttribute(require_utils.SPAN_OUTPUT, serialize(output));
|
|
592
592
|
} catch (serError) {
|
|
593
|
-
logger$
|
|
593
|
+
logger$31.warn("Failed to serialize response output: " + require_utils.errorMessage(serError));
|
|
594
594
|
}
|
|
595
595
|
if (error) span.recordException(error);
|
|
596
596
|
} catch (err) {
|
|
597
597
|
span.recordException(err);
|
|
598
598
|
} finally {
|
|
599
|
-
logger$
|
|
599
|
+
logger$31.debug("Ending span for Response");
|
|
600
600
|
span.end();
|
|
601
601
|
}
|
|
602
602
|
});
|
|
603
603
|
return newResponse;
|
|
604
604
|
}
|
|
605
|
-
logger$
|
|
605
|
+
logger$31.warn("Stream type not handled, ending span immediately");
|
|
606
606
|
span.end();
|
|
607
607
|
return originalResult;
|
|
608
608
|
};
|
|
@@ -680,7 +680,7 @@ const writeDebugSessionFile = (file, dir = process.cwd()) => {
|
|
|
680
680
|
* contract. This file is part of the cross-language parity surface — keep its
|
|
681
681
|
* logic line-comparable with the Python `config.py`.
|
|
682
682
|
*/
|
|
683
|
-
const logger$
|
|
683
|
+
const logger$30 = require_utils.initializeLogger();
|
|
684
684
|
const TRUTHY = /* @__PURE__ */ new Set([
|
|
685
685
|
"true",
|
|
686
686
|
"1",
|
|
@@ -716,7 +716,7 @@ const parseCacheUntil = (value) => {
|
|
|
716
716
|
if (value === void 0 || value === "") return null;
|
|
717
717
|
const spanId = normalizeSpanId(value);
|
|
718
718
|
if (spanId !== null) return spanId;
|
|
719
|
-
logger$
|
|
719
|
+
logger$30.warn(`LMNR_DEBUG_CACHE_UNTIL=${JSON.stringify(value)} is not a span id; ignoring`);
|
|
720
720
|
return null;
|
|
721
721
|
};
|
|
722
722
|
/**
|
|
@@ -1070,7 +1070,7 @@ const resetDebugRuntime = () => {
|
|
|
1070
1070
|
};
|
|
1071
1071
|
//#endregion
|
|
1072
1072
|
//#region src/opentelemetry-lib/tracing/span.ts
|
|
1073
|
-
const logger$
|
|
1073
|
+
const logger$29 = require_utils.initializeLogger();
|
|
1074
1074
|
/**
|
|
1075
1075
|
* Build the debug block to propagate, or undefined when debug mode is off.
|
|
1076
1076
|
*
|
|
@@ -1220,7 +1220,7 @@ var LaminarSpan = class LaminarSpan {
|
|
|
1220
1220
|
} catch {}
|
|
1221
1221
|
metadata[key.replace(`${require_utils.ASSOCIATION_PROPERTIES}.metadata.`, "")] = value;
|
|
1222
1222
|
}
|
|
1223
|
-
} else logger$
|
|
1223
|
+
} else logger$29.warn("Attributes object is not available. Most likely the span is not a LaminarSpan and not an OpenTelemetry default SDK Span. Span path and ids path will be empty.");
|
|
1224
1224
|
return {
|
|
1225
1225
|
spanId: require_utils.otelSpanIdToUUID(this._span.spanContext().spanId),
|
|
1226
1226
|
traceId: require_utils.otelTraceIdToUUID(this._span.spanContext().traceId),
|
|
@@ -1247,14 +1247,14 @@ var LaminarSpan = class LaminarSpan {
|
|
|
1247
1247
|
}
|
|
1248
1248
|
get tags() {
|
|
1249
1249
|
if (!this._span.attributes) {
|
|
1250
|
-
logger$
|
|
1250
|
+
logger$29.warn("[LaminarSpan.tags] WARNING. Current span does not have attributes object. Possibly, the span was created with a custom OTel SDK. Returning an empty list. Help: OpenTelemetry API does not guarantee reading attributes from a span, but OTel SDK allows it by default. Laminar SDK allows to read attributes too.");
|
|
1251
1251
|
return [];
|
|
1252
1252
|
}
|
|
1253
1253
|
return this._span.attributes[`lmnr.association.properties.tags`] ?? [];
|
|
1254
1254
|
}
|
|
1255
1255
|
get laminarAssociationProperties() {
|
|
1256
1256
|
if (!this._span.attributes) {
|
|
1257
|
-
logger$
|
|
1257
|
+
logger$29.warn("[LaminarSpan.laminarAssociationProperties] WARNING. Current span does not have attributes object. Possibly, the span was created with a custom OTel SDK. Returning an empty object. Help: OpenTelemetry API does not guarantee reading attributes from a span, but OTel SDK allows it by default. Laminar SDK allows to read attributes too.");
|
|
1258
1258
|
return {};
|
|
1259
1259
|
}
|
|
1260
1260
|
try {
|
|
@@ -1450,7 +1450,7 @@ var LaminarContextManager = class {
|
|
|
1450
1450
|
};
|
|
1451
1451
|
//#endregion
|
|
1452
1452
|
//#region src/opentelemetry-lib/instrumentation/claude-agent-sdk/proxy.ts
|
|
1453
|
-
const logger$
|
|
1453
|
+
const logger$28 = require_utils.initializeLogger();
|
|
1454
1454
|
const DEFAULT_ANTHROPIC_BASE_URL = "https://api.anthropic.com";
|
|
1455
1455
|
const DEFAULT_CC_PROXY_PORT = 45667;
|
|
1456
1456
|
const CC_PROXY_PORT_ATTEMPTS = 50;
|
|
@@ -1704,7 +1704,7 @@ const resolveTargetUrlFromEnv = (envDict, fallback = DEFAULT_ANTHROPIC_BASE_URL,
|
|
|
1704
1704
|
if (foundryBaseUrl) return foundryBaseUrl.replace(/\/$/, "");
|
|
1705
1705
|
const foundryResource = getEnvValue(FOUNDRY_RESOURCE_ENV);
|
|
1706
1706
|
if (foundryResource) return `https://${foundryResource}.services.ai.azure.com/anthropic`;
|
|
1707
|
-
logger$
|
|
1707
|
+
logger$28.error(`${FOUNDRY_USE_ENV} is set but neither ${FOUNDRY_BASE_URL_ENV} nor ${FOUNDRY_RESOURCE_ENV} is configured. Microsoft Foundry requires one of these values.`);
|
|
1708
1708
|
return null;
|
|
1709
1709
|
}
|
|
1710
1710
|
if (isTruthyEnv(getEnvValue(BEDROCK_USE_ENV))) {
|
|
@@ -1716,7 +1716,7 @@ const resolveTargetUrlFromEnv = (envDict, fallback = DEFAULT_ANTHROPIC_BASE_URL,
|
|
|
1716
1716
|
region = getRegionFromAwsConfig(awsProfile) ?? void 0;
|
|
1717
1717
|
}
|
|
1718
1718
|
if (region) return `https://bedrock-runtime.${region}.amazonaws.com`;
|
|
1719
|
-
logger$
|
|
1719
|
+
logger$28.error(`${BEDROCK_USE_ENV} is set but could not determine AWS region. Set ${BEDROCK_AWS_REGION_ENV} or configure a region in ~/.aws/config for the active profile.`);
|
|
1720
1720
|
return null;
|
|
1721
1721
|
}
|
|
1722
1722
|
if (isTruthyEnv(getEnvValue(VERTEX_USE_ENV))) {
|
|
@@ -1799,11 +1799,11 @@ const waitForPort = (port, timeoutMs = 5e3) => new Promise((resolve) => {
|
|
|
1799
1799
|
const registerGlobalProxyShutdown = () => {
|
|
1800
1800
|
if (!globalShutdownRegistered) {
|
|
1801
1801
|
process.on("exit", () => {
|
|
1802
|
-
logger$
|
|
1802
|
+
logger$28.debug("process.on(\"exit\") called - stopping all active proxies");
|
|
1803
1803
|
for (const proxyServer of activeProxyServers) try {
|
|
1804
1804
|
proxyServer.stopServer();
|
|
1805
1805
|
} catch (e) {
|
|
1806
|
-
logger$
|
|
1806
|
+
logger$28.debug(`Failed to stop proxy: ${require_utils.errorMessage(e)}`);
|
|
1807
1807
|
}
|
|
1808
1808
|
activeProxyServers.clear();
|
|
1809
1809
|
});
|
|
@@ -1818,28 +1818,28 @@ const createProxyInstance = async ({ env, cwd, settingSources, settings, targetU
|
|
|
1818
1818
|
try {
|
|
1819
1819
|
const port = await findAvailablePort(DEFAULT_CC_PROXY_PORT, CC_PROXY_PORT_ATTEMPTS);
|
|
1820
1820
|
if (port === null) {
|
|
1821
|
-
logger$
|
|
1821
|
+
logger$28.warn("Unable to allocate port for cc-proxy.");
|
|
1822
1822
|
return null;
|
|
1823
1823
|
}
|
|
1824
1824
|
const targetUrl = resolvedTargetUrl ?? resolveTargetUrlFromEnv(env, void 0, cwd, settingSources, settings);
|
|
1825
1825
|
if (!targetUrl) {
|
|
1826
|
-
logger$
|
|
1826
|
+
logger$28.warn("Unable to resolve target URL for cc-proxy (provider misconfigured).");
|
|
1827
1827
|
return null;
|
|
1828
1828
|
}
|
|
1829
|
-
logger$
|
|
1829
|
+
logger$28.debug(`Creating proxy instance on port ${port} targeting: ${targetUrl}`);
|
|
1830
1830
|
try {
|
|
1831
1831
|
const { ProxyServer } = require("@lmnr-ai/claude-code-proxy");
|
|
1832
1832
|
const proxyServer = new ProxyServer(port);
|
|
1833
1833
|
proxyServer.runServer(targetUrl);
|
|
1834
1834
|
if (!await waitForPort(port)) {
|
|
1835
|
-
logger$
|
|
1835
|
+
logger$28.warn(`cc-proxy failed to start on port ${port}`);
|
|
1836
1836
|
proxyServer.stopServer();
|
|
1837
1837
|
return null;
|
|
1838
1838
|
}
|
|
1839
1839
|
const proxyBaseUrl = `http://127.0.0.1:${port}`;
|
|
1840
1840
|
activeProxyServers.add(proxyServer);
|
|
1841
1841
|
registerGlobalProxyShutdown();
|
|
1842
|
-
logger$
|
|
1842
|
+
logger$28.info(`Started claude proxy server on: ${proxyBaseUrl}`);
|
|
1843
1843
|
return {
|
|
1844
1844
|
server: proxyServer,
|
|
1845
1845
|
baseUrl: proxyBaseUrl,
|
|
@@ -1847,11 +1847,11 @@ const createProxyInstance = async ({ env, cwd, settingSources, settings, targetU
|
|
|
1847
1847
|
targetUrl
|
|
1848
1848
|
};
|
|
1849
1849
|
} catch (e) {
|
|
1850
|
-
logger$
|
|
1850
|
+
logger$28.warn(`Unable to start cc-proxy: ${require_utils.errorMessage(e)}`);
|
|
1851
1851
|
return null;
|
|
1852
1852
|
}
|
|
1853
1853
|
} catch (e) {
|
|
1854
|
-
logger$
|
|
1854
|
+
logger$28.warn(`Failed to create proxy instance: ${require_utils.errorMessage(e)}`);
|
|
1855
1855
|
return null;
|
|
1856
1856
|
}
|
|
1857
1857
|
};
|
|
@@ -1861,11 +1861,11 @@ const createProxyInstance = async ({ env, cwd, settingSources, settings, targetU
|
|
|
1861
1861
|
const stopProxyInstance = (instance) => {
|
|
1862
1862
|
if (!instance) return;
|
|
1863
1863
|
try {
|
|
1864
|
-
logger$
|
|
1864
|
+
logger$28.debug(`Stopping proxy instance on port ${instance.port}`);
|
|
1865
1865
|
instance.server.stopServer();
|
|
1866
1866
|
activeProxyServers.delete(instance.server);
|
|
1867
1867
|
} catch (e) {
|
|
1868
|
-
logger$
|
|
1868
|
+
logger$28.debug(`Failed to stop proxy instance: ${require_utils.errorMessage(e)}`);
|
|
1869
1869
|
}
|
|
1870
1870
|
};
|
|
1871
1871
|
/**
|
|
@@ -1873,11 +1873,11 @@ const stopProxyInstance = (instance) => {
|
|
|
1873
1873
|
* Used during shutdown to ensure cleanup
|
|
1874
1874
|
*/
|
|
1875
1875
|
const forceReleaseProxy = () => {
|
|
1876
|
-
logger$
|
|
1876
|
+
logger$28.debug(`Force stopping all ${activeProxyServers.size} active proxy servers`);
|
|
1877
1877
|
for (const proxyServer of activeProxyServers) try {
|
|
1878
1878
|
proxyServer.stopServer();
|
|
1879
1879
|
} catch (e) {
|
|
1880
|
-
logger$
|
|
1880
|
+
logger$28.debug(`Failed to stop proxy: ${require_utils.errorMessage(e)}`);
|
|
1881
1881
|
}
|
|
1882
1882
|
activeProxyServers.clear();
|
|
1883
1883
|
};
|
|
@@ -1927,14 +1927,14 @@ const setTraceToProxyInstance = async (instance) => {
|
|
|
1927
1927
|
spanPath: payload.span_path,
|
|
1928
1928
|
laminarUrl: payload.laminar_url
|
|
1929
1929
|
});
|
|
1930
|
-
logger$
|
|
1930
|
+
logger$28.debug(`Set trace context to proxy on port ${instance.port}`);
|
|
1931
1931
|
} catch (e) {
|
|
1932
|
-
logger$
|
|
1932
|
+
logger$28.debug(`Unable to set trace context to proxy on port ${instance.port}: ` + require_utils.errorMessage(e));
|
|
1933
1933
|
}
|
|
1934
1934
|
};
|
|
1935
1935
|
//#endregion
|
|
1936
1936
|
//#region src/opentelemetry-lib/instrumentation/claude-agent-sdk/index.ts
|
|
1937
|
-
const logger$
|
|
1937
|
+
const logger$27 = require_utils.initializeLogger();
|
|
1938
1938
|
/**
|
|
1939
1939
|
* Create an instrumented version of the claude-agent-sdk query function.
|
|
1940
1940
|
* This can be used when importing the query function before Laminar initialization.
|
|
@@ -1970,9 +1970,9 @@ function instrumentClaudeAgentQuery(originalQuery) {
|
|
|
1970
1970
|
targetUrl
|
|
1971
1971
|
});
|
|
1972
1972
|
if (proxyInstance && targetUrl) {
|
|
1973
|
-
logger$
|
|
1973
|
+
logger$27.debug(`Using proxy on port ${proxyInstance.port}`);
|
|
1974
1974
|
await Laminar.withSpan(span, async () => {
|
|
1975
|
-
logger$
|
|
1975
|
+
logger$27.debug("Setting trace to proxy instance...");
|
|
1976
1976
|
await setTraceToProxyInstance(proxyInstance);
|
|
1977
1977
|
});
|
|
1978
1978
|
const varsToRemove = getEnvVarsToRemove(mergedEnv, sessionCwd, settingSources);
|
|
@@ -1987,13 +1987,13 @@ function instrumentClaudeAgentQuery(originalQuery) {
|
|
|
1987
1987
|
if (isProviderEnabledInEnv(subprocessEnv, "CLAUDE_CODE_USE_BEDROCK")) subprocessEnv.ANTHROPIC_BEDROCK_BASE_URL = proxyInstance.baseUrl;
|
|
1988
1988
|
if (isProviderEnabledInEnv(subprocessEnv, "CLAUDE_CODE_USE_VERTEX")) subprocessEnv.ANTHROPIC_VERTEX_BASE_URL = proxyInstance.baseUrl;
|
|
1989
1989
|
const flagSettings = buildProxyFlagSettings(callerSettings, proxyInstance.baseUrl, sessionCwd, settingSources);
|
|
1990
|
-
if (flagSettings === null) logger$
|
|
1990
|
+
if (flagSettings === null) logger$27.warn(`Could not read options.settings ${JSON.stringify(callerSettings)}; Claude Code settings that define a base URL will bypass the Laminar proxy and produce no LLM spans.`);
|
|
1991
1991
|
else {
|
|
1992
1992
|
params.options.settings = flagSettings;
|
|
1993
1993
|
const conflicting = Object.entries(readClaudeSettingsEnv(sessionCwd, settingSources)).filter(([key, value]) => PROXY_BASE_URL_ENV_KEYS.includes(key) && value !== "" && value !== proxyInstance?.baseUrl).map(([key]) => key);
|
|
1994
|
-
if (conflicting.length > 0) logger$
|
|
1994
|
+
if (conflicting.length > 0) logger$27.info(`Claude Code settings define ${conflicting.sort().join(", ")}, which outranks the subprocess environment. Injected settings so the Laminar proxy at ${proxyInstance.baseUrl} still intercepts API traffic; your settings files were not modified.`);
|
|
1995
1995
|
}
|
|
1996
|
-
} else logger$
|
|
1996
|
+
} else logger$27.debug("No claude proxy server available. Proceeding without proxy.");
|
|
1997
1997
|
const originalGenerator = originalQuery(params);
|
|
1998
1998
|
for await (const message of originalGenerator) {
|
|
1999
1999
|
collected.push(message);
|
|
@@ -2022,7 +2022,7 @@ var ClaudeAgentSDKInstrumentation = class extends _opentelemetry_instrumentation
|
|
|
2022
2022
|
}
|
|
2023
2023
|
manuallyInstrument(claudeAgentModule) {
|
|
2024
2024
|
if (claudeAgentModule.query && typeof claudeAgentModule.query === "function") this._wrap(claudeAgentModule, "query", this.patchQuery());
|
|
2025
|
-
else logger$
|
|
2025
|
+
else logger$27.debug("query function not found in claudeAgentSDK module, skipping instrumentation");
|
|
2026
2026
|
}
|
|
2027
2027
|
patchQuery() {
|
|
2028
2028
|
return (original) => instrumentClaudeAgentQuery(original);
|
|
@@ -2038,9 +2038,19 @@ var ClaudeAgentSDKInstrumentation = class extends _opentelemetry_instrumentation
|
|
|
2038
2038
|
}
|
|
2039
2039
|
};
|
|
2040
2040
|
//#endregion
|
|
2041
|
+
//#region src/opentelemetry-lib/instrumentation/langchain/llm-call.ts
|
|
2042
|
+
/**
|
|
2043
|
+
* Context key carrying the LangChain LLM call currently in progress. Set by the
|
|
2044
|
+
* `BaseChatModel` / `BaseLLM` wrappers for the duration of the model call.
|
|
2045
|
+
*
|
|
2046
|
+
* Kept free of other imports: `Laminar._startSpan` reads it to tell a handed
|
|
2047
|
+
* off call that the provider SDK instrumentation did record its span.
|
|
2048
|
+
*/
|
|
2049
|
+
const LLM_CALL_KEY = (0, _opentelemetry_api.createContextKey)("lmnr.langchain.llm_call");
|
|
2050
|
+
//#endregion
|
|
2041
2051
|
//#region src/laminar.ts
|
|
2042
2052
|
require_utils.loadEnv();
|
|
2043
|
-
const logger$
|
|
2053
|
+
const logger$26 = require_utils.initializeLogger();
|
|
2044
2054
|
var Laminar = class Laminar {
|
|
2045
2055
|
static {
|
|
2046
2056
|
this.isInitialized = false;
|
|
@@ -2112,28 +2122,32 @@ var Laminar = class Laminar {
|
|
|
2112
2122
|
* and you want Laminar spans to be children of the existing spans.
|
|
2113
2123
|
* @param {SpanProcessor} props.spanProcessor - The span processor to use. If passed, some of
|
|
2114
2124
|
* the other options will be ignored.
|
|
2125
|
+
* @param {string} props.release - The release of the running code, usually its git commit
|
|
2126
|
+
* SHA. Laminar groups an agent's traces into versions by release. If not specified, read
|
|
2127
|
+
* from the LMNR_RELEASE environment variable, common deploy platform variables (Vercel,
|
|
2128
|
+
* Render, Railway, Heroku, Cloud Run, ...), or the checked-out git commit.
|
|
2115
2129
|
*
|
|
2116
2130
|
* @example
|
|
2117
2131
|
* import { Laminar } from '@lmnr-ai/lmnr';
|
|
2118
2132
|
* import { OpenAI } from 'openai';
|
|
2119
|
-
* import * as
|
|
2133
|
+
* import * as CallbackManagerModule from "@langchain/core/callbacks/manager";
|
|
2120
2134
|
*
|
|
2121
|
-
* // Initialize Laminar while
|
|
2135
|
+
* // Initialize Laminar while instrumenting LangChain and OpenAI modules.
|
|
2122
2136
|
* Laminar.initialize({
|
|
2123
2137
|
* projectApiKey: "<LMNR_PROJECT_API_KEY>",
|
|
2124
2138
|
* instrumentModules: {
|
|
2125
2139
|
* langchain: {
|
|
2126
|
-
*
|
|
2140
|
+
* callbackManagerModule: CallbackManagerModule
|
|
2127
2141
|
* },
|
|
2128
|
-
*
|
|
2142
|
+
* OpenAI: OpenAI
|
|
2129
2143
|
* }
|
|
2130
2144
|
* });
|
|
2131
2145
|
*
|
|
2132
2146
|
* @throws {Error} - If project API key is not set
|
|
2133
2147
|
*/
|
|
2134
|
-
static initialize({ projectApiKey, baseUrl, baseHttpUrl, httpPort, grpcPort, instrumentModules, disableBatch, traceExportTimeoutMillis, logLevel, maxExportBatchSize, maxExportBatchSizeBytes, flushBySize, forceHttp, sessionRecordingOptions, metadata, inheritGlobalContext, spanProcessor } = {}) {
|
|
2148
|
+
static initialize({ projectApiKey, baseUrl, baseHttpUrl, httpPort, grpcPort, instrumentModules, disableBatch, traceExportTimeoutMillis, logLevel, maxExportBatchSize, maxExportBatchSizeBytes, flushBySize, forceHttp, sessionRecordingOptions, metadata, inheritGlobalContext, spanProcessor, release } = {}) {
|
|
2135
2149
|
if (this.isInitialized) {
|
|
2136
|
-
logger$
|
|
2150
|
+
logger$26.warn("Laminar has already been initialized. Skipping initialization.");
|
|
2137
2151
|
return;
|
|
2138
2152
|
}
|
|
2139
2153
|
const key = projectApiKey ?? process?.env?.LMNR_PROJECT_API_KEY;
|
|
@@ -2157,7 +2171,7 @@ var Laminar = class Laminar {
|
|
|
2157
2171
|
...metadata ?? {}
|
|
2158
2172
|
};
|
|
2159
2173
|
if (inheritGlobalContext) LaminarContextManager.inheritGlobalContext = true;
|
|
2160
|
-
if (spanProcessor && !(spanProcessor instanceof LaminarSpanProcessor)) logger$
|
|
2174
|
+
if (spanProcessor && !(spanProcessor instanceof LaminarSpanProcessor)) logger$26.warn("Span processor is not a LaminarSpanProcessor. Some functionality may be impaired.");
|
|
2161
2175
|
this.isInitialized = true;
|
|
2162
2176
|
const urlWithoutSlash = url?.replace(/\/$/, "").replace(/:\d{1,5}$/g, "");
|
|
2163
2177
|
const httpUrlWithoutSlash = httpUrl?.replace(/\/$/, "").replace(/:\d{1,5}$/g, "");
|
|
@@ -2177,7 +2191,8 @@ var Laminar = class Laminar {
|
|
|
2177
2191
|
flushBySize,
|
|
2178
2192
|
traceExportTimeoutMillis,
|
|
2179
2193
|
sessionRecordingOptions,
|
|
2180
|
-
spanProcessor
|
|
2194
|
+
spanProcessor,
|
|
2195
|
+
release
|
|
2181
2196
|
});
|
|
2182
2197
|
this._initDebugRuntime(url, port);
|
|
2183
2198
|
LaminarContextManager.setGlobalMetadata(this.globalMetadata);
|
|
@@ -2204,11 +2219,11 @@ var Laminar = class Laminar {
|
|
|
2204
2219
|
try {
|
|
2205
2220
|
getRuntime()?.recordTraceId(require_utils.otelTraceIdToUUID(otelSpanContext.traceId));
|
|
2206
2221
|
} catch (e) {
|
|
2207
|
-
logger$
|
|
2222
|
+
logger$26.debug("Failed to record debug trace id from env: " + require_utils.errorMessage(e));
|
|
2208
2223
|
}
|
|
2209
|
-
logger$
|
|
2224
|
+
logger$26.debug("Initialized Laminar parent context from LMNR_SPAN_CONTEXT.");
|
|
2210
2225
|
} catch (e) {
|
|
2211
|
-
logger$
|
|
2226
|
+
logger$26.warn("LMNR_SPAN_CONTEXT is set but could not be used: " + require_utils.errorMessage(e));
|
|
2212
2227
|
}
|
|
2213
2228
|
}
|
|
2214
2229
|
/**
|
|
@@ -2252,7 +2267,7 @@ var Laminar = class Laminar {
|
|
|
2252
2267
|
if (projectId) {
|
|
2253
2268
|
runtime.recordProjectId(projectId);
|
|
2254
2269
|
const sessionUrl = runtime.debuggerSessionUrl();
|
|
2255
|
-
logger$
|
|
2270
|
+
logger$26.info(`Laminar debugger session: ${sessionUrl}`);
|
|
2256
2271
|
if (runtime.shouldOpenBrowser) {
|
|
2257
2272
|
const opener = process.platform === "win32" ? "start" : process.platform === "darwin" ? "open" : "xdg-open";
|
|
2258
2273
|
(0, node_child_process.spawn)(opener, [sessionUrl], {
|
|
@@ -2262,7 +2277,7 @@ var Laminar = class Laminar {
|
|
|
2262
2277
|
}
|
|
2263
2278
|
}
|
|
2264
2279
|
}).catch((e) => {
|
|
2265
|
-
logger$
|
|
2280
|
+
logger$26.warn("Failed to register debug session: " + require_utils.errorMessage(e));
|
|
2266
2281
|
});
|
|
2267
2282
|
this.globalMetadata = {
|
|
2268
2283
|
...this.globalMetadata,
|
|
@@ -2272,7 +2287,7 @@ var Laminar = class Laminar {
|
|
|
2272
2287
|
this.debugExitHook = () => runtime.emitPointer();
|
|
2273
2288
|
process.once("exit", this.debugExitHook);
|
|
2274
2289
|
} catch (e) {
|
|
2275
|
-
logger$
|
|
2290
|
+
logger$26.warn("Failed to initialize debug runtime: " + require_utils.errorMessage(e));
|
|
2276
2291
|
}
|
|
2277
2292
|
}
|
|
2278
2293
|
/**
|
|
@@ -2319,7 +2334,7 @@ var Laminar = class Laminar {
|
|
|
2319
2334
|
runtime.rolloutSessions.register({ sessionId: runtime.sessionId }).then((projectId) => {
|
|
2320
2335
|
if (projectId) runtime.recordProjectId(projectId);
|
|
2321
2336
|
}).catch((e) => {
|
|
2322
|
-
logger$
|
|
2337
|
+
logger$26.debug("Failed to register downstream debug session: " + require_utils.errorMessage(e));
|
|
2323
2338
|
});
|
|
2324
2339
|
this.globalMetadata = {
|
|
2325
2340
|
...this.globalMetadata,
|
|
@@ -2328,7 +2343,7 @@ var Laminar = class Laminar {
|
|
|
2328
2343
|
LaminarContextManager.setGlobalMetadata(this.globalMetadata);
|
|
2329
2344
|
}
|
|
2330
2345
|
} catch (e) {
|
|
2331
|
-
logger$
|
|
2346
|
+
logger$26.debug("Failed to arm debug runtime from context: " + require_utils.errorMessage(e));
|
|
2332
2347
|
}
|
|
2333
2348
|
}
|
|
2334
2349
|
/**
|
|
@@ -2343,7 +2358,7 @@ var Laminar = class Laminar {
|
|
|
2343
2358
|
*/
|
|
2344
2359
|
static patch(modules) {
|
|
2345
2360
|
if (!this.isInitialized) {
|
|
2346
|
-
logger$
|
|
2361
|
+
logger$26.warn("Laminar must be initialized before patching modules. Skipping patch.");
|
|
2347
2362
|
return;
|
|
2348
2363
|
}
|
|
2349
2364
|
if (!modules || Object.keys(modules).length === 0) throw new Error("Pass at least one module to patch");
|
|
@@ -2603,7 +2618,7 @@ var Laminar = class Laminar {
|
|
|
2603
2618
|
const spanContext = require_utils.tryToOtelSpanContext(laminarContext);
|
|
2604
2619
|
entityContext = _opentelemetry_api.trace.setSpan(entityContext, _opentelemetry_api.trace.wrapSpanContext(spanContext));
|
|
2605
2620
|
} catch (e) {
|
|
2606
|
-
logger$
|
|
2621
|
+
logger$26.warn("Failed to parse parent span context: " + require_utils.errorMessage(e));
|
|
2607
2622
|
}
|
|
2608
2623
|
const tagProperties = tags ? { [`${require_utils.ASSOCIATION_PROPERTIES}.tags`]: Array.from(new Set(tags)) } : {};
|
|
2609
2624
|
const ctxAssociationProperties = LaminarContextManager.getAssociationProperties();
|
|
@@ -2639,6 +2654,10 @@ var Laminar = class Laminar {
|
|
|
2639
2654
|
startTime
|
|
2640
2655
|
}, entityContext));
|
|
2641
2656
|
span.activated = activated ?? false;
|
|
2657
|
+
if (spanType === "LLM") {
|
|
2658
|
+
const llmCall = entityContext.getValue(LLM_CALL_KEY);
|
|
2659
|
+
if (llmCall?.mode === "handoff" && span.isRecording()) llmCall.recorded = true;
|
|
2660
|
+
}
|
|
2642
2661
|
if (input) span.setInput(input);
|
|
2643
2662
|
if (activated) {
|
|
2644
2663
|
entityContext = LaminarContextManager.setAssociationProperties(span, entityContext);
|
|
@@ -2707,13 +2726,13 @@ var Laminar = class Laminar {
|
|
|
2707
2726
|
}
|
|
2708
2727
|
static async flush() {
|
|
2709
2728
|
if (this.isInitialized) {
|
|
2710
|
-
logger$
|
|
2729
|
+
logger$26.debug("Flushing spans");
|
|
2711
2730
|
await forceFlush();
|
|
2712
2731
|
}
|
|
2713
2732
|
}
|
|
2714
2733
|
static async shutdown() {
|
|
2715
2734
|
if (this.isInitialized) {
|
|
2716
|
-
logger$
|
|
2735
|
+
logger$26.debug("Shutting down Laminar");
|
|
2717
2736
|
getRuntime()?.emitPointer();
|
|
2718
2737
|
await forceFlush();
|
|
2719
2738
|
this.isInitialized = false;
|
|
@@ -2848,7 +2867,7 @@ return module.exports;
|
|
|
2848
2867
|
//#endregion
|
|
2849
2868
|
//#region src/browser/utils.ts
|
|
2850
2869
|
const LMNR_SEND_EVENTS_FUNCTION_NAME = "lmnrSendEvents";
|
|
2851
|
-
const logger$
|
|
2870
|
+
const logger$25 = require_utils.initializeLogger();
|
|
2852
2871
|
/**
|
|
2853
2872
|
* If the first argument is a string, return an object with the name of the method
|
|
2854
2873
|
* and the argument as the value.
|
|
@@ -2871,7 +2890,7 @@ const takeFullSnapshot = async (page) => await page.evaluate(() => {
|
|
|
2871
2890
|
window.lmnrRrweb.record.takeFullSnapshot();
|
|
2872
2891
|
return true;
|
|
2873
2892
|
} catch (error) {
|
|
2874
|
-
logger$
|
|
2893
|
+
logger$25.error("Error taking full snapshot: " + require_utils.errorMessage(error));
|
|
2875
2894
|
return false;
|
|
2876
2895
|
}
|
|
2877
2896
|
return false;
|
|
@@ -2882,7 +2901,7 @@ const injectSessionRecorder = async (page, sessionRecordingOptions) => {
|
|
|
2882
2901
|
try {
|
|
2883
2902
|
return await script();
|
|
2884
2903
|
} catch (error) {
|
|
2885
|
-
logger$
|
|
2904
|
+
logger$25.error("Operation " + script.name + " failed: " + require_utils.errorMessage(error));
|
|
2886
2905
|
}
|
|
2887
2906
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
2888
2907
|
}
|
|
@@ -2892,20 +2911,20 @@ const injectSessionRecorder = async (page, sessionRecordingOptions) => {
|
|
|
2892
2911
|
try {
|
|
2893
2912
|
isRrwebPresent = await castedPage.evaluate(() => typeof window.lmnrRrweb !== "undefined");
|
|
2894
2913
|
} catch (error) {
|
|
2895
|
-
logger$
|
|
2914
|
+
logger$25.debug("Failed to check if session recorder is loaded: " + require_utils.errorMessage(error));
|
|
2896
2915
|
}
|
|
2897
2916
|
if (!isRrwebPresent) {
|
|
2898
2917
|
if (!await tryRunScript(async function injectSessionRecorder() {
|
|
2899
2918
|
await castedPage.evaluate(RECORDER);
|
|
2900
2919
|
return true;
|
|
2901
2920
|
})) {
|
|
2902
|
-
logger$
|
|
2921
|
+
logger$25.error("Failed to load session recorder");
|
|
2903
2922
|
return;
|
|
2904
2923
|
}
|
|
2905
2924
|
try {
|
|
2906
2925
|
await castedPage.evaluate(injectScript, sessionRecordingOptions);
|
|
2907
2926
|
} catch (error) {
|
|
2908
|
-
logger$
|
|
2927
|
+
logger$25.debug("Failed to inject session recorder: " + require_utils.errorMessage(error));
|
|
2909
2928
|
}
|
|
2910
2929
|
}
|
|
2911
2930
|
};
|
|
@@ -3171,7 +3190,7 @@ async function sendEvents(chunk, client, chunkBuffers, sessionId, traceId) {
|
|
|
3171
3190
|
try {
|
|
3172
3191
|
const { batchId, chunkIndex, totalChunks, data } = chunk;
|
|
3173
3192
|
if (!sessionId || !traceId) {
|
|
3174
|
-
logger$
|
|
3193
|
+
logger$25.debug("Missing sessionId or traceId in chunk");
|
|
3175
3194
|
return;
|
|
3176
3195
|
}
|
|
3177
3196
|
if (!chunkBuffers.has(batchId)) chunkBuffers.set(batchId, {
|
|
@@ -3190,7 +3209,7 @@ async function sendEvents(chunk, client, chunkBuffers, sessionId, traceId) {
|
|
|
3190
3209
|
traceId,
|
|
3191
3210
|
events
|
|
3192
3211
|
}).catch((error) => {
|
|
3193
|
-
logger$
|
|
3212
|
+
logger$25.debug("Failed to send events: " + require_utils.errorMessage(error));
|
|
3194
3213
|
});
|
|
3195
3214
|
chunkBuffers.delete(batchId);
|
|
3196
3215
|
}
|
|
@@ -3198,16 +3217,16 @@ async function sendEvents(chunk, client, chunkBuffers, sessionId, traceId) {
|
|
|
3198
3217
|
const toDelete = [];
|
|
3199
3218
|
for (const [bid, buffer] of chunkBuffers.entries()) if (currentTime - buffer.timestamp > OLD_BUFFER_TIMEOUT) toDelete.push(bid);
|
|
3200
3219
|
for (const bid of toDelete) {
|
|
3201
|
-
logger$
|
|
3220
|
+
logger$25.debug(`Cleaning up incomplete chunk buffer: ${bid}`);
|
|
3202
3221
|
chunkBuffers.delete(bid);
|
|
3203
3222
|
}
|
|
3204
3223
|
} catch (error) {
|
|
3205
|
-
logger$
|
|
3224
|
+
logger$25.debug("Could not send events: " + require_utils.errorMessage(error));
|
|
3206
3225
|
}
|
|
3207
3226
|
}
|
|
3208
3227
|
//#endregion
|
|
3209
3228
|
//#region src/browser/playwright.ts
|
|
3210
|
-
const logger$
|
|
3229
|
+
const logger$24 = require_utils.initializeLogger();
|
|
3211
3230
|
var PlaywrightInstrumentation = class extends _opentelemetry_instrumentation.InstrumentationBase {
|
|
3212
3231
|
constructor(client, sessionRecordingOptions) {
|
|
3213
3232
|
super("@lmnr/playwright-instrumentation", require_utils.version, { enabled: true });
|
|
@@ -3315,7 +3334,7 @@ var PlaywrightInstrumentation = class extends _opentelemetry_instrumentation.Ins
|
|
|
3315
3334
|
try {
|
|
3316
3335
|
await injectSessionRecorder(page, this._sessionRecordingOptions);
|
|
3317
3336
|
} catch (error) {
|
|
3318
|
-
logger$
|
|
3337
|
+
logger$24.error("Error in onLoad handler: " + require_utils.errorMessage(error));
|
|
3319
3338
|
}
|
|
3320
3339
|
});
|
|
3321
3340
|
const chunkBuffers = /* @__PURE__ */ new Map();
|
|
@@ -3325,7 +3344,7 @@ var PlaywrightInstrumentation = class extends _opentelemetry_instrumentation.Ins
|
|
|
3325
3344
|
await sendEvents(chunk, this._client, chunkBuffers, sessionId, traceId);
|
|
3326
3345
|
});
|
|
3327
3346
|
} catch (error) {
|
|
3328
|
-
logger$
|
|
3347
|
+
logger$24.debug("Could not expose function lmnrSendEvents: " + require_utils.errorMessage(error));
|
|
3329
3348
|
}
|
|
3330
3349
|
}
|
|
3331
3350
|
};
|
|
@@ -3750,7 +3769,7 @@ var StagehandV2Instrumentation = class extends _opentelemetry_instrumentation.In
|
|
|
3750
3769
|
};
|
|
3751
3770
|
//#endregion
|
|
3752
3771
|
//#region src/browser/puppeteer.ts
|
|
3753
|
-
const logger$
|
|
3772
|
+
const logger$23 = require_utils.initializeLogger();
|
|
3754
3773
|
var PuppeteerInstrumentation = class extends _opentelemetry_instrumentation.InstrumentationBase {
|
|
3755
3774
|
constructor(client, sessionRecordingOptions) {
|
|
3756
3775
|
super("@lmnr/puppeteer-instrumentation", require_utils.version, { enabled: true });
|
|
@@ -3795,10 +3814,10 @@ var PuppeteerInstrumentation = class extends _opentelemetry_instrumentation.Inst
|
|
|
3795
3814
|
context.on("targetcreated", (target) => {
|
|
3796
3815
|
target.page().then((page) => {
|
|
3797
3816
|
if (page) plugin.patchPage(page, sessionId).catch((error) => {
|
|
3798
|
-
logger$
|
|
3817
|
+
logger$23.error("Failed to patch page: " + require_utils.errorMessage(error));
|
|
3799
3818
|
});
|
|
3800
3819
|
}).catch((error) => {
|
|
3801
|
-
logger$
|
|
3820
|
+
logger$23.error("Failed to patch page: " + require_utils.errorMessage(error));
|
|
3802
3821
|
});
|
|
3803
3822
|
});
|
|
3804
3823
|
await Promise.all((await context.pages()).map((page) => plugin.patchPage(page, sessionId)));
|
|
@@ -3816,19 +3835,19 @@ var PuppeteerInstrumentation = class extends _opentelemetry_instrumentation.Inst
|
|
|
3816
3835
|
context.on("targetcreated", (target) => {
|
|
3817
3836
|
target.page().then((page) => {
|
|
3818
3837
|
if (page) plugin.patchPage(page, sessionId).catch((error) => {
|
|
3819
|
-
logger$
|
|
3838
|
+
logger$23.error("Failed to patch page: " + require_utils.errorMessage(error));
|
|
3820
3839
|
});
|
|
3821
3840
|
}).catch((error) => {
|
|
3822
|
-
logger$
|
|
3841
|
+
logger$23.error("Failed to patch page: " + require_utils.errorMessage(error));
|
|
3823
3842
|
});
|
|
3824
3843
|
});
|
|
3825
3844
|
context.on("targetchanged", (target) => {
|
|
3826
3845
|
target.page().then((page) => {
|
|
3827
3846
|
if (page) plugin.patchPage(page, sessionId).catch((error) => {
|
|
3828
|
-
logger$
|
|
3847
|
+
logger$23.error("Failed to patch page: " + require_utils.errorMessage(error));
|
|
3829
3848
|
});
|
|
3830
3849
|
}).catch((error) => {
|
|
3831
|
-
logger$
|
|
3850
|
+
logger$23.error("Failed to patch page: " + require_utils.errorMessage(error));
|
|
3832
3851
|
});
|
|
3833
3852
|
});
|
|
3834
3853
|
for (const page of await context.pages()) await plugin.patchPage(page, sessionId);
|
|
@@ -3852,7 +3871,7 @@ var PuppeteerInstrumentation = class extends _opentelemetry_instrumentation.Inst
|
|
|
3852
3871
|
const traceId = otelTraceId ? require_utils.otelTraceIdToUUID(otelTraceId) : require_utils.NIL_UUID;
|
|
3853
3872
|
page.on("domcontentloaded", () => {
|
|
3854
3873
|
injectSessionRecorder(page, this._sessionRecordingOptions).catch((error) => {
|
|
3855
|
-
logger$
|
|
3874
|
+
logger$23.error("Error in onLoad handler: " + require_utils.errorMessage(error));
|
|
3856
3875
|
});
|
|
3857
3876
|
});
|
|
3858
3877
|
await injectSessionRecorder(page, this._sessionRecordingOptions);
|
|
@@ -3862,13 +3881,13 @@ var PuppeteerInstrumentation = class extends _opentelemetry_instrumentation.Inst
|
|
|
3862
3881
|
await sendEvents(chunk, this._client, chunkBuffers, sessionId, traceId);
|
|
3863
3882
|
});
|
|
3864
3883
|
} catch (error) {
|
|
3865
|
-
logger$
|
|
3884
|
+
logger$23.debug("Could not expose function lmnrSendEvents: " + require_utils.errorMessage(error));
|
|
3866
3885
|
}
|
|
3867
3886
|
}
|
|
3868
3887
|
};
|
|
3869
3888
|
//#endregion
|
|
3870
3889
|
//#region src/browser/stagehand/v3/constants.ts
|
|
3871
|
-
const logger$
|
|
3890
|
+
const logger$22 = require_utils.initializeLogger();
|
|
3872
3891
|
const CDP_OPERATION_TIMEOUT_MS = 1e4;
|
|
3873
3892
|
const SKIP_URL_PATTERNS = [
|
|
3874
3893
|
"about:blank",
|
|
@@ -3919,7 +3938,7 @@ async function getOrCreateIsolatedWorld(page) {
|
|
|
3919
3938
|
frameId
|
|
3920
3939
|
};
|
|
3921
3940
|
} catch (error) {
|
|
3922
|
-
logger$
|
|
3941
|
+
logger$22.debug("Failed to create isolated world: " + require_utils.errorMessage(error));
|
|
3923
3942
|
return null;
|
|
3924
3943
|
}
|
|
3925
3944
|
}
|
|
@@ -3936,7 +3955,7 @@ async function isRecorderPresent(page, contextId) {
|
|
|
3936
3955
|
if (!result) return true;
|
|
3937
3956
|
return result.result?.value === true;
|
|
3938
3957
|
} catch (error) {
|
|
3939
|
-
logger$
|
|
3958
|
+
logger$22.debug("Failed to check if recorder is present: " + require_utils.errorMessage(error));
|
|
3940
3959
|
return true;
|
|
3941
3960
|
}
|
|
3942
3961
|
}
|
|
@@ -3949,21 +3968,21 @@ async function injectRecorderViaCDP(page, state, conn, sessionRecordingOptions,
|
|
|
3949
3968
|
try {
|
|
3950
3969
|
url = page.url();
|
|
3951
3970
|
} catch (error) {
|
|
3952
|
-
logger$
|
|
3971
|
+
logger$22.debug("Failed to get page URL, page might be closed: " + require_utils.errorMessage(error));
|
|
3953
3972
|
return null;
|
|
3954
3973
|
}
|
|
3955
3974
|
if (shouldSkipUrl(url)) {
|
|
3956
|
-
logger$
|
|
3975
|
+
logger$22.debug(`Skipping recorder injection for URL: ${url}`);
|
|
3957
3976
|
return null;
|
|
3958
3977
|
}
|
|
3959
3978
|
const worldResult = await getOrCreateIsolatedWorld(page);
|
|
3960
3979
|
if (!worldResult) {
|
|
3961
|
-
logger$
|
|
3980
|
+
logger$22.debug("Failed to get isolated world for page");
|
|
3962
3981
|
return null;
|
|
3963
3982
|
}
|
|
3964
3983
|
const { contextId, frameId } = worldResult;
|
|
3965
3984
|
if (await isRecorderPresent(page, contextId)) {
|
|
3966
|
-
logger$
|
|
3985
|
+
logger$22.debug("Recorder already present, skipping injection");
|
|
3967
3986
|
state.contextIdToSession.set(contextId, {
|
|
3968
3987
|
sessionId: state.sessionId,
|
|
3969
3988
|
traceId: state.traceId
|
|
@@ -3976,7 +3995,7 @@ async function injectRecorderViaCDP(page, state, conn, sessionRecordingOptions,
|
|
|
3976
3995
|
contextId
|
|
3977
3996
|
});
|
|
3978
3997
|
} catch (error) {
|
|
3979
|
-
logger$
|
|
3998
|
+
logger$22.debug("Failed to inject rrweb: " + require_utils.errorMessage(error));
|
|
3980
3999
|
return null;
|
|
3981
4000
|
}
|
|
3982
4001
|
const optionsJson = JSON.stringify(sessionRecordingOptions ?? {});
|
|
@@ -3987,14 +4006,14 @@ async function injectRecorderViaCDP(page, state, conn, sessionRecordingOptions,
|
|
|
3987
4006
|
contextId
|
|
3988
4007
|
});
|
|
3989
4008
|
} catch (error) {
|
|
3990
|
-
logger$
|
|
4009
|
+
logger$22.debug("Failed to inject recording setup: " + require_utils.errorMessage(error));
|
|
3991
4010
|
return null;
|
|
3992
4011
|
}
|
|
3993
4012
|
try {
|
|
3994
4013
|
await sendCDP(page, "Runtime.addBinding", { name: "lmnrSendEvents" });
|
|
3995
|
-
logger$
|
|
4014
|
+
logger$22.debug(`Added binding 'lmnrSendEvents' for page ${frameId}, context ${contextId}`);
|
|
3996
4015
|
} catch (error) {
|
|
3997
|
-
logger$
|
|
4016
|
+
logger$22.debug("Binding may already exist: " + require_utils.errorMessage(error));
|
|
3998
4017
|
}
|
|
3999
4018
|
if (bindingHandler) try {
|
|
4000
4019
|
const pageTargetId = page.targetId();
|
|
@@ -4004,26 +4023,26 @@ async function injectRecorderViaCDP(page, state, conn, sessionRecordingOptions,
|
|
|
4004
4023
|
const sessionTyped = session;
|
|
4005
4024
|
if (sessionTyped.on) {
|
|
4006
4025
|
sessionTyped.on("Runtime.bindingCalled", bindingHandler);
|
|
4007
|
-
logger$
|
|
4026
|
+
logger$22.debug(`Set up binding handler on session ${sessionId}`);
|
|
4008
4027
|
}
|
|
4009
4028
|
} catch (error) {
|
|
4010
|
-
logger$
|
|
4029
|
+
logger$22.debug(`Failed to set up binding handler on session ${sessionId}: ` + require_utils.errorMessage(error));
|
|
4011
4030
|
}
|
|
4012
4031
|
state.pageSessionHandlers.set(pageTargetId, bindingHandler);
|
|
4013
4032
|
}
|
|
4014
4033
|
} catch (error) {
|
|
4015
|
-
logger$
|
|
4034
|
+
logger$22.debug("Failed to set up binding handler: " + require_utils.errorMessage(error));
|
|
4016
4035
|
}
|
|
4017
4036
|
state.contextIdToSession.set(contextId, {
|
|
4018
4037
|
sessionId: state.sessionId,
|
|
4019
4038
|
traceId: state.traceId
|
|
4020
4039
|
});
|
|
4021
|
-
logger$
|
|
4040
|
+
logger$22.debug(`Registered context mapping: contextId=${contextId}, sessionId=${state.sessionId}`);
|
|
4022
4041
|
state.instrumentedPageIds.add(frameId);
|
|
4023
|
-
logger$
|
|
4042
|
+
logger$22.debug(`Successfully injected recorder into page ${frameId}`);
|
|
4024
4043
|
return contextId;
|
|
4025
4044
|
} catch (error) {
|
|
4026
|
-
logger$
|
|
4045
|
+
logger$22.debug("Error injecting recorder: " + require_utils.errorMessage(error));
|
|
4027
4046
|
return null;
|
|
4028
4047
|
}
|
|
4029
4048
|
}
|
|
@@ -4037,13 +4056,13 @@ function createBindingHandler(state) {
|
|
|
4037
4056
|
if (event.name !== "lmnrSendEvents") return;
|
|
4038
4057
|
const sessionInfo = state.contextIdToSession.get(event.executionContextId);
|
|
4039
4058
|
if (!sessionInfo) {
|
|
4040
|
-
logger$
|
|
4059
|
+
logger$22.debug("No session info found for context ID: " + event.executionContextId);
|
|
4041
4060
|
if (state.contextIdToSession.size > 0) {
|
|
4042
4061
|
const [, fallbackInfo] = state.contextIdToSession.entries().next().value;
|
|
4043
4062
|
if (fallbackInfo) try {
|
|
4044
4063
|
sendEvents(JSON.parse(event.payload), state.client, state.chunkBuffers, fallbackInfo.sessionId, fallbackInfo.traceId);
|
|
4045
4064
|
} catch (error) {
|
|
4046
|
-
logger$
|
|
4065
|
+
logger$22.debug("Failed to parse binding payload: " + require_utils.errorMessage(error));
|
|
4047
4066
|
}
|
|
4048
4067
|
}
|
|
4049
4068
|
return;
|
|
@@ -4051,7 +4070,7 @@ function createBindingHandler(state) {
|
|
|
4051
4070
|
try {
|
|
4052
4071
|
sendEvents(JSON.parse(event.payload), state.client, state.chunkBuffers, sessionInfo.sessionId, sessionInfo.traceId);
|
|
4053
4072
|
} catch (error) {
|
|
4054
|
-
logger$
|
|
4073
|
+
logger$22.debug("Failed to handle binding event: " + require_utils.errorMessage(error));
|
|
4055
4074
|
}
|
|
4056
4075
|
};
|
|
4057
4076
|
}
|
|
@@ -4067,10 +4086,10 @@ function createTargetCreatedHandler(context, state, sessionRecordingOptions) {
|
|
|
4067
4086
|
const pageId = page.mainFrameId();
|
|
4068
4087
|
if (!state.instrumentedPageIds.has(pageId)) await injectRecorderViaCDP(page, state, context.conn, sessionRecordingOptions, state.bindingHandler ?? void 0);
|
|
4069
4088
|
} catch (error) {
|
|
4070
|
-
logger$
|
|
4089
|
+
logger$22.debug("Error injecting recorder into new page: " + require_utils.errorMessage(error));
|
|
4071
4090
|
}
|
|
4072
4091
|
} catch (error) {
|
|
4073
|
-
logger$
|
|
4092
|
+
logger$22.debug("Error handling target created event: " + require_utils.errorMessage(error));
|
|
4074
4093
|
}
|
|
4075
4094
|
};
|
|
4076
4095
|
}
|
|
@@ -4082,7 +4101,7 @@ function createTargetInfoChangedHandler(context, state, sessionRecordingOptions)
|
|
|
4082
4101
|
if (event.targetInfo.type !== "page") return;
|
|
4083
4102
|
const url = event.targetInfo.url;
|
|
4084
4103
|
if (shouldSkipUrl(url)) return;
|
|
4085
|
-
logger$
|
|
4104
|
+
logger$22.debug(`Target URL changed to ${url}, checking if recorder injection needed`);
|
|
4086
4105
|
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
4087
4106
|
try {
|
|
4088
4107
|
for (const page of context.pages()) if (page.targetId() === event.targetInfo.targetId) {
|
|
@@ -4090,7 +4109,7 @@ function createTargetInfoChangedHandler(context, state, sessionRecordingOptions)
|
|
|
4090
4109
|
break;
|
|
4091
4110
|
}
|
|
4092
4111
|
} catch (error) {
|
|
4093
|
-
logger$
|
|
4112
|
+
logger$22.debug("Error handling target info change: " + require_utils.errorMessage(error));
|
|
4094
4113
|
}
|
|
4095
4114
|
};
|
|
4096
4115
|
}
|
|
@@ -4251,12 +4270,12 @@ var StagehandInstrumentation = class extends _opentelemetry_instrumentation.Inst
|
|
|
4251
4270
|
*/
|
|
4252
4271
|
async setupSessionRecording(stagehandInstance, sessionId, traceId) {
|
|
4253
4272
|
if (!this._client) {
|
|
4254
|
-
logger$
|
|
4273
|
+
logger$22.debug("No Laminar client available, skipping session recording setup");
|
|
4255
4274
|
return;
|
|
4256
4275
|
}
|
|
4257
4276
|
const context = stagehandInstance.context;
|
|
4258
4277
|
if (!context || !context.conn) {
|
|
4259
|
-
logger$
|
|
4278
|
+
logger$22.debug("No context or connection available, skipping session recording setup");
|
|
4260
4279
|
return;
|
|
4261
4280
|
}
|
|
4262
4281
|
const recorderState = {
|
|
@@ -4286,11 +4305,11 @@ var StagehandInstrumentation = class extends _opentelemetry_instrumentation.Inst
|
|
|
4286
4305
|
for (const page of pages) try {
|
|
4287
4306
|
if (await injectRecorderViaCDP(page, recorderState, context.conn, this._sessionRecordingOptions, bindingHandler) !== null) injectedCount++;
|
|
4288
4307
|
} catch (error) {
|
|
4289
|
-
logger$
|
|
4308
|
+
logger$22.debug("Error injecting recorder into page: " + require_utils.errorMessage(error));
|
|
4290
4309
|
}
|
|
4291
|
-
logger$
|
|
4310
|
+
logger$22.debug(`Injected session recorder into ${injectedCount} of ${pages.length} existing page(s)`);
|
|
4292
4311
|
} catch (error) {
|
|
4293
|
-
logger$
|
|
4312
|
+
logger$22.debug("Error accessing pages for recorder injection: " + require_utils.errorMessage(error));
|
|
4294
4313
|
}
|
|
4295
4314
|
}
|
|
4296
4315
|
patchStagehandClose() {
|
|
@@ -4320,12 +4339,12 @@ var StagehandInstrumentation = class extends _opentelemetry_instrumentation.Inst
|
|
|
4320
4339
|
if (recorderState.targetCreatedHandler) try {
|
|
4321
4340
|
context.conn.off("Target.targetCreated", recorderState.targetCreatedHandler);
|
|
4322
4341
|
} catch (error) {
|
|
4323
|
-
logger$
|
|
4342
|
+
logger$22.debug("Error removing target created handler: " + require_utils.errorMessage(error));
|
|
4324
4343
|
}
|
|
4325
4344
|
if (recorderState.targetInfoChangedHandler) try {
|
|
4326
4345
|
context.conn.off("Target.targetInfoChanged", recorderState.targetInfoChangedHandler);
|
|
4327
4346
|
} catch (error) {
|
|
4328
|
-
logger$
|
|
4347
|
+
logger$22.debug("Error removing target info changed handler: " + require_utils.errorMessage(error));
|
|
4329
4348
|
}
|
|
4330
4349
|
}
|
|
4331
4350
|
recorderState.contextIdToSession.clear();
|
|
@@ -4336,7 +4355,7 @@ var StagehandInstrumentation = class extends _opentelemetry_instrumentation.Inst
|
|
|
4336
4355
|
recorderState.targetCreatedHandler = null;
|
|
4337
4356
|
recorderState.targetInfoChangedHandler = null;
|
|
4338
4357
|
this.stagehandInstanceToRecorderState.delete(stagehandInstance);
|
|
4339
|
-
logger$
|
|
4358
|
+
logger$22.debug("Cleaned up session recording for Stagehand instance");
|
|
4340
4359
|
}
|
|
4341
4360
|
patchStagehandGlobalMethod(methodName, sessionId, parentSpan) {
|
|
4342
4361
|
return (original) => async function method(...args) {
|
|
@@ -4687,7 +4706,7 @@ function extractToolDefinitions(config) {
|
|
|
4687
4706
|
* Also used by the google-aiplatform (Vertex AI) instrumentation, which
|
|
4688
4707
|
* reshapes its requests into the same `{model, contents, config}` form.
|
|
4689
4708
|
*/
|
|
4690
|
-
function setRequestAttributes$
|
|
4709
|
+
function setRequestAttributes$6(span, params, traceContent, system = "gemini") {
|
|
4691
4710
|
safeSetAttribute$2(span, LLM_SYSTEM, system);
|
|
4692
4711
|
safeSetAttribute$2(span, LLM_REQUEST_MODEL, params?.model);
|
|
4693
4712
|
const config = params?.config;
|
|
@@ -4714,7 +4733,7 @@ function setRequestAttributes$5(span, params, traceContent, system = "gemini") {
|
|
|
4714
4733
|
/**
|
|
4715
4734
|
* Set response attributes on a span from a GenerateContentResponse.
|
|
4716
4735
|
*/
|
|
4717
|
-
function setResponseAttributes$
|
|
4736
|
+
function setResponseAttributes$6(span, response, traceContent) {
|
|
4718
4737
|
if (!response) return;
|
|
4719
4738
|
safeSetAttribute$2(span, LLM_RESPONSE_MODEL, response.modelVersion);
|
|
4720
4739
|
const usage = response.usageMetadata;
|
|
@@ -4816,7 +4835,7 @@ function wrapStreamingResponse(span, asyncGen, traceContent) {
|
|
|
4816
4835
|
try {
|
|
4817
4836
|
if (modelVersion !== void 0 || role !== void 0 || accumulatedParts.length > 0 || sawUsageMetadata) {
|
|
4818
4837
|
const mergedParts = mergeTextParts(accumulatedParts);
|
|
4819
|
-
setResponseAttributes$
|
|
4838
|
+
setResponseAttributes$6(span, {
|
|
4820
4839
|
modelVersion,
|
|
4821
4840
|
candidates: [{ content: {
|
|
4822
4841
|
role: role ?? "model",
|
|
@@ -4847,22 +4866,22 @@ function wrapStreamingResponse(span, asyncGen, traceContent) {
|
|
|
4847
4866
|
//#endregion
|
|
4848
4867
|
//#region src/opentelemetry-lib/instrumentation/anthropic/utils.ts
|
|
4849
4868
|
const ANTHROPIC_SYSTEM = "anthropic";
|
|
4850
|
-
const INPUT_MESSAGES$
|
|
4851
|
-
const OUTPUT_MESSAGES$
|
|
4869
|
+
const INPUT_MESSAGES$3 = "gen_ai.input.messages";
|
|
4870
|
+
const OUTPUT_MESSAGES$3 = "gen_ai.output.messages";
|
|
4852
4871
|
const createStreamState$1 = () => ({
|
|
4853
4872
|
usage: {},
|
|
4854
4873
|
blocks: [],
|
|
4855
4874
|
completion: ""
|
|
4856
4875
|
});
|
|
4857
|
-
const toJson$
|
|
4876
|
+
const toJson$2 = (value) => {
|
|
4858
4877
|
if (value === void 0 || value === null) return void 0;
|
|
4859
4878
|
return JSON.stringify(value);
|
|
4860
4879
|
};
|
|
4861
4880
|
const extractStructuredOutputSchema$1 = (params) => {
|
|
4862
4881
|
const outputFormat = params?.output_format;
|
|
4863
|
-
if (outputFormat && typeof outputFormat === "object") return toJson$
|
|
4882
|
+
if (outputFormat && typeof outputFormat === "object") return toJson$2(outputFormat.schema ?? outputFormat);
|
|
4864
4883
|
const schema = params?.output_config?.format?.schema;
|
|
4865
|
-
if (schema && typeof schema === "object") return toJson$
|
|
4884
|
+
if (schema && typeof schema === "object") return toJson$2(schema);
|
|
4866
4885
|
};
|
|
4867
4886
|
const buildInputMessages$1 = (params) => {
|
|
4868
4887
|
if (params?.prompt !== void 0 && params?.prompt !== null) return [{
|
|
@@ -4878,7 +4897,7 @@ const buildInputMessages$1 = (params) => {
|
|
|
4878
4897
|
messages.push(...params.messages);
|
|
4879
4898
|
return messages;
|
|
4880
4899
|
};
|
|
4881
|
-
const setRequestAttributes$
|
|
4900
|
+
const setRequestAttributes$5 = (span, params, traceContent) => {
|
|
4882
4901
|
safeSetAttribute$2(span, "gen_ai.system", ANTHROPIC_SYSTEM);
|
|
4883
4902
|
safeSetAttribute$2(span, "gen_ai.request.model", params?.model);
|
|
4884
4903
|
safeSetAttribute$2(span, "gen_ai.request.max_tokens", params?.max_tokens ?? params?.max_tokens_to_sample);
|
|
@@ -4889,8 +4908,8 @@ const setRequestAttributes$4 = (span, params, traceContent) => {
|
|
|
4889
4908
|
safeSetAttribute$2(span, "llm.is_streaming", params?.stream);
|
|
4890
4909
|
safeSetAttribute$2(span, "anthropic.request.service_tier", params?.service_tier);
|
|
4891
4910
|
if (traceContent) {
|
|
4892
|
-
safeSetAttribute$2(span, INPUT_MESSAGES$
|
|
4893
|
-
safeSetAttribute$2(span, "gen_ai.tool.definitions", toJson$
|
|
4911
|
+
safeSetAttribute$2(span, INPUT_MESSAGES$3, toJson$2(buildInputMessages$1(params)));
|
|
4912
|
+
safeSetAttribute$2(span, "gen_ai.tool.definitions", toJson$2(params?.tools));
|
|
4894
4913
|
}
|
|
4895
4914
|
safeSetAttribute$2(span, "gen_ai.request.structured_output_schema", extractStructuredOutputSchema$1(params));
|
|
4896
4915
|
};
|
|
@@ -4910,7 +4929,7 @@ const setUsageAttributes$1 = (span, usage, includeTotal) => {
|
|
|
4910
4929
|
/**
|
|
4911
4930
|
* Response attributes for a non-streaming `Message` (or legacy `Completion`).
|
|
4912
4931
|
*/
|
|
4913
|
-
const setResponseAttributes$
|
|
4932
|
+
const setResponseAttributes$5 = (span, response, traceContent) => {
|
|
4914
4933
|
if (!response || typeof response !== "object") return;
|
|
4915
4934
|
safeSetAttribute$2(span, "gen_ai.response.model", response.model);
|
|
4916
4935
|
safeSetAttribute$2(span, "gen_ai.response.id", response.id);
|
|
@@ -4927,7 +4946,7 @@ const setResponseAttributes$4 = (span, response, traceContent) => {
|
|
|
4927
4946
|
text: response.completion
|
|
4928
4947
|
});
|
|
4929
4948
|
else if (Array.isArray(response.content)) output.content.push(...response.content);
|
|
4930
|
-
safeSetAttribute$2(span, OUTPUT_MESSAGES$
|
|
4949
|
+
safeSetAttribute$2(span, OUTPUT_MESSAGES$3, toJson$2([output]));
|
|
4931
4950
|
}
|
|
4932
4951
|
span.setStatus({ code: _opentelemetry_api.SpanStatusCode.OK });
|
|
4933
4952
|
};
|
|
@@ -5020,14 +5039,14 @@ const setStreamingResponseAttributes = (span, state, traceContent) => {
|
|
|
5020
5039
|
content: buildStreamedContent(state)
|
|
5021
5040
|
};
|
|
5022
5041
|
if (state.stopReason) output.stop_reason = state.stopReason;
|
|
5023
|
-
safeSetAttribute$2(span, OUTPUT_MESSAGES$
|
|
5042
|
+
safeSetAttribute$2(span, OUTPUT_MESSAGES$3, toJson$2([output]));
|
|
5024
5043
|
}
|
|
5025
5044
|
};
|
|
5026
5045
|
//#endregion
|
|
5027
5046
|
//#region src/opentelemetry-lib/instrumentation/anthropic/index.ts
|
|
5028
|
-
const logger$
|
|
5029
|
-
const PATCH_DATA_SYMBOL$
|
|
5030
|
-
const hasOwnPatchData$
|
|
5047
|
+
const logger$21 = require_utils.initializeLogger();
|
|
5048
|
+
const PATCH_DATA_SYMBOL$4 = Symbol("lmnr.anthropic.patchData");
|
|
5049
|
+
const hasOwnPatchData$3 = (proto) => Object.getOwnPropertyDescriptor(proto, PATCH_DATA_SYMBOL$4) !== void 0;
|
|
5031
5050
|
const markSpanError$3 = (span, error) => {
|
|
5032
5051
|
span.recordException(error);
|
|
5033
5052
|
span.setAttribute("error.type", error?.constructor?.name ?? "Error");
|
|
@@ -5040,7 +5059,7 @@ const safely$3 = (fn) => {
|
|
|
5040
5059
|
try {
|
|
5041
5060
|
fn();
|
|
5042
5061
|
} catch (error) {
|
|
5043
|
-
logger$
|
|
5062
|
+
logger$21.debug(`Failed to set anthropic span attributes: ${String(error)}`);
|
|
5044
5063
|
}
|
|
5045
5064
|
};
|
|
5046
5065
|
const isAsyncIterable$3 = (value) => value !== null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function";
|
|
@@ -5091,9 +5110,9 @@ var AnthropicInstrumentation = class extends _opentelemetry_instrumentation.Inst
|
|
|
5091
5110
|
unpatch(moduleExports) {
|
|
5092
5111
|
_opentelemetry_api.diag.debug("Unpatching @anthropic-ai/sdk");
|
|
5093
5112
|
for (const proto of this.resourcePrototypes(moduleExports)) {
|
|
5094
|
-
if (!proto || !hasOwnPatchData$
|
|
5095
|
-
proto.create = proto[PATCH_DATA_SYMBOL$
|
|
5096
|
-
delete proto[PATCH_DATA_SYMBOL$
|
|
5113
|
+
if (!proto || !hasOwnPatchData$3(proto)) continue;
|
|
5114
|
+
proto.create = proto[PATCH_DATA_SYMBOL$4].original;
|
|
5115
|
+
delete proto[PATCH_DATA_SYMBOL$4];
|
|
5097
5116
|
}
|
|
5098
5117
|
}
|
|
5099
5118
|
/**
|
|
@@ -5115,15 +5134,15 @@ var AnthropicInstrumentation = class extends _opentelemetry_instrumentation.Inst
|
|
|
5115
5134
|
*/
|
|
5116
5135
|
patchCreate(proto, spanName) {
|
|
5117
5136
|
if (!proto || typeof proto.create !== "function") return;
|
|
5118
|
-
if (hasOwnPatchData$
|
|
5119
|
-
proto[PATCH_DATA_SYMBOL$
|
|
5137
|
+
if (hasOwnPatchData$3(proto)) {
|
|
5138
|
+
proto[PATCH_DATA_SYMBOL$4].traceContent = this.traceContent;
|
|
5120
5139
|
return;
|
|
5121
5140
|
}
|
|
5122
5141
|
const patchData = {
|
|
5123
5142
|
traceContent: this.traceContent,
|
|
5124
5143
|
original: proto.create
|
|
5125
5144
|
};
|
|
5126
|
-
Object.defineProperty(proto, PATCH_DATA_SYMBOL$
|
|
5145
|
+
Object.defineProperty(proto, PATCH_DATA_SYMBOL$4, {
|
|
5127
5146
|
value: patchData,
|
|
5128
5147
|
writable: true,
|
|
5129
5148
|
configurable: true,
|
|
@@ -5140,7 +5159,7 @@ const wrapCreate = (patchData, spanName) => function(params, ...rest) {
|
|
|
5140
5159
|
name: spanName,
|
|
5141
5160
|
spanType: "LLM"
|
|
5142
5161
|
});
|
|
5143
|
-
safely$3(() => setRequestAttributes$
|
|
5162
|
+
safely$3(() => setRequestAttributes$5(span, params, traceContent));
|
|
5144
5163
|
let result;
|
|
5145
5164
|
try {
|
|
5146
5165
|
result = Laminar.withSpan(span, () => ({ value: original.call(this, params, ...rest) })).value;
|
|
@@ -5164,7 +5183,7 @@ const wrapCreate = (patchData, spanName) => function(params, ...rest) {
|
|
|
5164
5183
|
return data;
|
|
5165
5184
|
}
|
|
5166
5185
|
ended = true;
|
|
5167
|
-
safely$3(() => setResponseAttributes$
|
|
5186
|
+
safely$3(() => setResponseAttributes$5(span, data, traceContent));
|
|
5168
5187
|
span.end();
|
|
5169
5188
|
return data;
|
|
5170
5189
|
};
|
|
@@ -5214,8 +5233,8 @@ const instrumentStream$2 = (stream, span, traceContent) => {
|
|
|
5214
5233
|
//#endregion
|
|
5215
5234
|
//#region src/opentelemetry-lib/instrumentation/cohere/utils.ts
|
|
5216
5235
|
const COHERE_SYSTEM = "cohere";
|
|
5217
|
-
const INPUT_MESSAGES$
|
|
5218
|
-
const OUTPUT_MESSAGES$
|
|
5236
|
+
const INPUT_MESSAGES$2 = "gen_ai.input.messages";
|
|
5237
|
+
const OUTPUT_MESSAGES$2 = "gen_ai.output.messages";
|
|
5219
5238
|
const OPERATION_NAMES = {
|
|
5220
5239
|
chat: "chat",
|
|
5221
5240
|
completion: "text_completion",
|
|
@@ -5230,7 +5249,7 @@ const V1_ROLES = {
|
|
|
5230
5249
|
};
|
|
5231
5250
|
const asList = (value) => Array.isArray(value) ? value : [];
|
|
5232
5251
|
const asInt = (value) => typeof value === "number" && Number.isFinite(value) ? Math.trunc(value) : void 0;
|
|
5233
|
-
const maybeJson = (value) => {
|
|
5252
|
+
const maybeJson$1 = (value) => {
|
|
5234
5253
|
if (typeof value !== "string") return value;
|
|
5235
5254
|
try {
|
|
5236
5255
|
return JSON.parse(value);
|
|
@@ -5298,7 +5317,7 @@ const v2ToolCallParts = (toolCalls) => asList(toolCalls).map((toolCall) => {
|
|
|
5298
5317
|
name: toolCall?.function?.name ?? ""
|
|
5299
5318
|
};
|
|
5300
5319
|
const args = toolCall?.function?.arguments;
|
|
5301
|
-
if (args !== void 0 && args !== null) part.arguments = maybeJson(args);
|
|
5320
|
+
if (args !== void 0 && args !== null) part.arguments = maybeJson$1(args);
|
|
5302
5321
|
return part;
|
|
5303
5322
|
});
|
|
5304
5323
|
const v1ToolCallParts = (toolCalls) => asList(toolCalls).map((toolCall) => ({
|
|
@@ -5388,7 +5407,7 @@ const toolDefinitions = (tools) => asList(tools).map((tool) => {
|
|
|
5388
5407
|
if (parameters) definition.parameters = parameters;
|
|
5389
5408
|
return definition;
|
|
5390
5409
|
});
|
|
5391
|
-
const setRequestAttributes$
|
|
5410
|
+
const setRequestAttributes$4 = (span, params, requestType, isV2, isStreaming, traceContent) => {
|
|
5392
5411
|
safeSetAttribute$2(span, "gen_ai.system", COHERE_SYSTEM);
|
|
5393
5412
|
safeSetAttribute$2(span, "gen_ai.operation.name", OPERATION_NAMES[requestType]);
|
|
5394
5413
|
safeSetAttribute$2(span, "gen_ai.request.model", params?.model);
|
|
@@ -5413,12 +5432,12 @@ const setRequestAttributes$3 = (span, params, requestType, isV2, isStreaming, tr
|
|
|
5413
5432
|
}] : [];
|
|
5414
5433
|
else if (requestType === "rerank") messages = rerankInput(params);
|
|
5415
5434
|
else messages = embedInput(params);
|
|
5416
|
-
if (messages.length > 0) span.setAttribute(INPUT_MESSAGES$
|
|
5435
|
+
if (messages.length > 0) span.setAttribute(INPUT_MESSAGES$2, JSON.stringify(messages));
|
|
5417
5436
|
};
|
|
5418
5437
|
/**
|
|
5419
5438
|
* `usage` (v2) / `meta` (v1): actual `tokens`, falling back to `billedUnits`.
|
|
5420
5439
|
*/
|
|
5421
|
-
const setUsage = (span, usage) => {
|
|
5440
|
+
const setUsage$1 = (span, usage) => {
|
|
5422
5441
|
const inputTokens = asInt(usage?.tokens?.inputTokens) ?? asInt(usage?.billedUnits?.inputTokens);
|
|
5423
5442
|
const outputTokens = asInt(usage?.tokens?.outputTokens) ?? asInt(usage?.billedUnits?.outputTokens);
|
|
5424
5443
|
safeSetAttribute$2(span, "gen_ai.usage.input_tokens", inputTokens);
|
|
@@ -5454,9 +5473,9 @@ const rerankOutput = (response) => {
|
|
|
5454
5473
|
parts
|
|
5455
5474
|
}] : [];
|
|
5456
5475
|
};
|
|
5457
|
-
const setResponseAttributes$
|
|
5476
|
+
const setResponseAttributes$4 = (span, response, requestType, isV2, traceContent) => {
|
|
5458
5477
|
safeSetAttribute$2(span, "gen_ai.response.id", response?.responseId ?? response?.id);
|
|
5459
|
-
setUsage(span, response?.usage ?? response?.meta);
|
|
5478
|
+
setUsage$1(span, response?.usage ?? response?.meta);
|
|
5460
5479
|
let output = [];
|
|
5461
5480
|
if (requestType === "chat") {
|
|
5462
5481
|
const message = isV2 ? v2ChatOutput(response) : v1ChatOutput(response);
|
|
@@ -5468,7 +5487,7 @@ const setResponseAttributes$3 = (span, response, requestType, isV2, traceContent
|
|
|
5468
5487
|
output = [message];
|
|
5469
5488
|
} else if (requestType === "completion") output = completionOutput(response);
|
|
5470
5489
|
else if (requestType === "rerank") output = rerankOutput(response);
|
|
5471
|
-
if (output.length > 0 && traceContent) span.setAttribute(OUTPUT_MESSAGES$
|
|
5490
|
+
if (output.length > 0 && traceContent) span.setAttribute(OUTPUT_MESSAGES$2, JSON.stringify(output));
|
|
5472
5491
|
};
|
|
5473
5492
|
/**
|
|
5474
5493
|
* v1 `chatStream`: the `stream-end` event carries the full response.
|
|
@@ -5585,8 +5604,8 @@ const createV2ChatStreamAccumulator = () => {
|
|
|
5585
5604
|
};
|
|
5586
5605
|
//#endregion
|
|
5587
5606
|
//#region src/opentelemetry-lib/instrumentation/cohere/index.ts
|
|
5588
|
-
const logger$
|
|
5589
|
-
const PATCH_DATA_SYMBOL$
|
|
5607
|
+
const logger$20 = require_utils.initializeLogger();
|
|
5608
|
+
const PATCH_DATA_SYMBOL$3 = Symbol("lmnr.cohere.patchData");
|
|
5590
5609
|
const SPAN_NAMES = {
|
|
5591
5610
|
chat: "cohere.chat",
|
|
5592
5611
|
completion: "cohere.completion",
|
|
@@ -5642,7 +5661,7 @@ const V2_METHODS = [
|
|
|
5642
5661
|
streaming: false
|
|
5643
5662
|
}
|
|
5644
5663
|
];
|
|
5645
|
-
const ownPatchData = (proto) => Object.getOwnPropertyDescriptor(proto, PATCH_DATA_SYMBOL$
|
|
5664
|
+
const ownPatchData = (proto) => Object.getOwnPropertyDescriptor(proto, PATCH_DATA_SYMBOL$3)?.value;
|
|
5646
5665
|
const markSpanError$2 = (span, error) => {
|
|
5647
5666
|
span.recordException(error);
|
|
5648
5667
|
span.setAttribute("error.type", error?.constructor?.name ?? "Error");
|
|
@@ -5658,7 +5677,7 @@ const safely$2 = (fn) => {
|
|
|
5658
5677
|
try {
|
|
5659
5678
|
fn();
|
|
5660
5679
|
} catch (error) {
|
|
5661
|
-
logger$
|
|
5680
|
+
logger$20.debug(`Failed to set cohere span attributes: ${String(error)}`);
|
|
5662
5681
|
}
|
|
5663
5682
|
};
|
|
5664
5683
|
const isAsyncIterable$2 = (value) => value !== null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function";
|
|
@@ -5765,7 +5784,7 @@ var CohereInstrumentation = class extends _opentelemetry_instrumentation.Instrum
|
|
|
5765
5784
|
}
|
|
5766
5785
|
if (!patched) {
|
|
5767
5786
|
patched = {};
|
|
5768
|
-
Object.defineProperty(proto, PATCH_DATA_SYMBOL$
|
|
5787
|
+
Object.defineProperty(proto, PATCH_DATA_SYMBOL$3, {
|
|
5769
5788
|
value: patched,
|
|
5770
5789
|
writable: true,
|
|
5771
5790
|
configurable: true,
|
|
@@ -5790,7 +5809,7 @@ const wrapMethod$1 = (patchData) => function(request, ...rest) {
|
|
|
5790
5809
|
name: SPAN_NAMES[requestType],
|
|
5791
5810
|
spanType: "LLM"
|
|
5792
5811
|
});
|
|
5793
|
-
safely$2(() => setRequestAttributes$
|
|
5812
|
+
safely$2(() => setRequestAttributes$4(span, request, requestType, isV2, streaming, traceContent));
|
|
5794
5813
|
let result;
|
|
5795
5814
|
try {
|
|
5796
5815
|
result = Laminar.withSpan(span, () => ({ value: original.call(this, request, ...rest) })).value;
|
|
@@ -5814,7 +5833,7 @@ const wrapMethod$1 = (patchData) => function(request, ...rest) {
|
|
|
5814
5833
|
instrumentStream$1(data, span, accumulator, isV2, traceContent);
|
|
5815
5834
|
return data;
|
|
5816
5835
|
}
|
|
5817
|
-
safely$2(() => setResponseAttributes$
|
|
5836
|
+
safely$2(() => setResponseAttributes$4(span, data, requestType, isV2, traceContent));
|
|
5818
5837
|
span.end();
|
|
5819
5838
|
return data;
|
|
5820
5839
|
};
|
|
@@ -5839,7 +5858,7 @@ const instrumentStream$1 = (stream, span, accumulator, isV2, traceContent) => {
|
|
|
5839
5858
|
const end = (error) => {
|
|
5840
5859
|
if (ended) return;
|
|
5841
5860
|
ended = true;
|
|
5842
|
-
safely$2(() => setResponseAttributes$
|
|
5861
|
+
safely$2(() => setResponseAttributes$4(span, accumulator.response(), "chat", isV2, traceContent));
|
|
5843
5862
|
if (error !== void 0) markSpanError$2(span, error);
|
|
5844
5863
|
else span.setStatus({ code: _opentelemetry_api.SpanStatusCode.OK });
|
|
5845
5864
|
span.end();
|
|
@@ -5889,7 +5908,7 @@ const fromValue = (value) => {
|
|
|
5889
5908
|
default: return;
|
|
5890
5909
|
}
|
|
5891
5910
|
};
|
|
5892
|
-
const asRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
5911
|
+
const asRecord$1 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
5893
5912
|
const asNumber = (value) => typeof value === "number" && !Number.isNaN(value) ? value : void 0;
|
|
5894
5913
|
/**
|
|
5895
5914
|
* Strip resource prefixes, e.g.
|
|
@@ -5910,7 +5929,7 @@ const toInputMessages = (instance) => {
|
|
|
5910
5929
|
content: instance.prompt
|
|
5911
5930
|
});
|
|
5912
5931
|
if (Array.isArray(instance.messages)) for (const message of instance.messages) {
|
|
5913
|
-
const record = asRecord(message);
|
|
5932
|
+
const record = asRecord$1(message);
|
|
5914
5933
|
if (!record) continue;
|
|
5915
5934
|
const author = typeof record.author === "string" ? record.author : "user";
|
|
5916
5935
|
messages.push({
|
|
@@ -5927,7 +5946,7 @@ const toInputMessages = (instance) => {
|
|
|
5927
5946
|
const setPredictRequestAttributes = (span, request, traceContent) => {
|
|
5928
5947
|
safeSetAttribute$2(span, "gen_ai.system", VERTEX_AI_SYSTEM);
|
|
5929
5948
|
safeSetAttribute$2(span, "gen_ai.request.model", lastPathSegment(request?.endpoint));
|
|
5930
|
-
const parameters = asRecord(fromValue(request?.parameters));
|
|
5949
|
+
const parameters = asRecord$1(fromValue(request?.parameters));
|
|
5931
5950
|
if (parameters) {
|
|
5932
5951
|
safeSetAttribute$2(span, "gen_ai.request.max_tokens", asNumber(parameters.maxOutputTokens));
|
|
5933
5952
|
safeSetAttribute$2(span, "gen_ai.request.temperature", asNumber(parameters.temperature));
|
|
@@ -5936,16 +5955,16 @@ const setPredictRequestAttributes = (span, request, traceContent) => {
|
|
|
5936
5955
|
}
|
|
5937
5956
|
if (!traceContent || !Array.isArray(request?.instances)) return;
|
|
5938
5957
|
const messages = request.instances.flatMap((instance) => {
|
|
5939
|
-
const record = asRecord(fromValue(instance));
|
|
5958
|
+
const record = asRecord$1(fromValue(instance));
|
|
5940
5959
|
return record ? toInputMessages(record) : [];
|
|
5941
5960
|
});
|
|
5942
5961
|
if (messages.length > 0) safeSetAttribute$2(span, "gen_ai.input.messages", JSON.stringify(messages));
|
|
5943
5962
|
};
|
|
5944
5963
|
const predictionContent = (prediction) => {
|
|
5945
|
-
const record = asRecord(fromValue(prediction));
|
|
5964
|
+
const record = asRecord$1(fromValue(prediction));
|
|
5946
5965
|
if (!record) return void 0;
|
|
5947
5966
|
if (typeof record.content === "string") return record.content;
|
|
5948
|
-
const firstCandidate = Array.isArray(record.candidates) ? asRecord(record.candidates[0]) : void 0;
|
|
5967
|
+
const firstCandidate = Array.isArray(record.candidates) ? asRecord$1(record.candidates[0]) : void 0;
|
|
5949
5968
|
if (typeof firstCandidate?.content === "string") return firstCandidate.content;
|
|
5950
5969
|
};
|
|
5951
5970
|
/**
|
|
@@ -5954,10 +5973,10 @@ const predictionContent = (prediction) => {
|
|
|
5954
5973
|
const setPredictResponseAttributes = (span, response, traceContent) => {
|
|
5955
5974
|
if (!response) return;
|
|
5956
5975
|
safeSetAttribute$2(span, "gen_ai.response.model", lastPathSegment(response.model));
|
|
5957
|
-
const metadata = asRecord(fromValue(response.metadata));
|
|
5958
|
-
const tokenMetadata = asRecord(metadata?.tokenMetadata);
|
|
5959
|
-
const inputTokens = asNumber(asRecord(tokenMetadata?.inputTokenCount)?.totalTokens);
|
|
5960
|
-
const outputTokens = asNumber(asRecord(tokenMetadata?.outputTokenCount)?.totalTokens);
|
|
5976
|
+
const metadata = asRecord$1(fromValue(response.metadata));
|
|
5977
|
+
const tokenMetadata = asRecord$1(metadata?.tokenMetadata);
|
|
5978
|
+
const inputTokens = asNumber(asRecord$1(tokenMetadata?.inputTokenCount)?.totalTokens);
|
|
5979
|
+
const outputTokens = asNumber(asRecord$1(tokenMetadata?.outputTokenCount)?.totalTokens);
|
|
5961
5980
|
safeSetAttribute$2(span, "gen_ai.usage.input_tokens", inputTokens);
|
|
5962
5981
|
safeSetAttribute$2(span, "gen_ai.usage.output_tokens", outputTokens);
|
|
5963
5982
|
if (inputTokens !== void 0 && outputTokens !== void 0) safeSetAttribute$2(span, "llm.usage.total_tokens", inputTokens + outputTokens);
|
|
@@ -5989,9 +6008,9 @@ const toGenAiParams = (model, request) => {
|
|
|
5989
6008
|
};
|
|
5990
6009
|
//#endregion
|
|
5991
6010
|
//#region src/opentelemetry-lib/instrumentation/google-aiplatform/index.ts
|
|
5992
|
-
const logger$
|
|
5993
|
-
const PATCH_DATA_SYMBOL$
|
|
5994
|
-
const hasOwnPatchData$
|
|
6011
|
+
const logger$19 = require_utils.initializeLogger();
|
|
6012
|
+
const PATCH_DATA_SYMBOL$2 = Symbol("lmnr.google-aiplatform.patchData");
|
|
6013
|
+
const hasOwnPatchData$2 = (proto) => Object.getOwnPropertyDescriptor(proto, PATCH_DATA_SYMBOL$2) !== void 0;
|
|
5995
6014
|
const GENERATIVE_MODEL_CLASSES = ["GenerativeModel", "GenerativeModelPreview"];
|
|
5996
6015
|
const markSpanError$1 = (span, error) => {
|
|
5997
6016
|
span.setAttribute("error.type", error?.constructor?.name ?? "Error");
|
|
@@ -6004,7 +6023,7 @@ const safely$1 = (fn) => {
|
|
|
6004
6023
|
try {
|
|
6005
6024
|
fn();
|
|
6006
6025
|
} catch (error) {
|
|
6007
|
-
logger$
|
|
6026
|
+
logger$19.debug(`Failed to set google-aiplatform span attributes: ${String(error)}`);
|
|
6008
6027
|
}
|
|
6009
6028
|
};
|
|
6010
6029
|
/**
|
|
@@ -6094,13 +6113,13 @@ var GoogleAIPlatformInstrumentation = class extends _opentelemetry_instrumentati
|
|
|
6094
6113
|
*/
|
|
6095
6114
|
patchMethod(proto, method, makeWrapper) {
|
|
6096
6115
|
if (!proto || typeof proto[method] !== "function") return;
|
|
6097
|
-
if (!hasOwnPatchData$
|
|
6116
|
+
if (!hasOwnPatchData$2(proto)) Object.defineProperty(proto, PATCH_DATA_SYMBOL$2, {
|
|
6098
6117
|
value: {},
|
|
6099
6118
|
writable: true,
|
|
6100
6119
|
configurable: true,
|
|
6101
6120
|
enumerable: false
|
|
6102
6121
|
});
|
|
6103
|
-
const patches = proto[PATCH_DATA_SYMBOL$
|
|
6122
|
+
const patches = proto[PATCH_DATA_SYMBOL$2];
|
|
6104
6123
|
const existing = patches[method];
|
|
6105
6124
|
if (existing) {
|
|
6106
6125
|
existing.traceContent = this.traceContent;
|
|
@@ -6114,10 +6133,10 @@ var GoogleAIPlatformInstrumentation = class extends _opentelemetry_instrumentati
|
|
|
6114
6133
|
proto[method] = makeWrapper(patchData.original, patchData);
|
|
6115
6134
|
}
|
|
6116
6135
|
unpatchMethods(proto) {
|
|
6117
|
-
if (!proto || !hasOwnPatchData$
|
|
6118
|
-
const patches = proto[PATCH_DATA_SYMBOL$
|
|
6136
|
+
if (!proto || !hasOwnPatchData$2(proto)) return;
|
|
6137
|
+
const patches = proto[PATCH_DATA_SYMBOL$2];
|
|
6119
6138
|
for (const [method, patchData] of Object.entries(patches)) proto[method] = patchData.original;
|
|
6120
|
-
delete proto[PATCH_DATA_SYMBOL$
|
|
6139
|
+
delete proto[PATCH_DATA_SYMBOL$2];
|
|
6121
6140
|
}
|
|
6122
6141
|
wrapGenerateContent(original, patchData) {
|
|
6123
6142
|
return function(request, ...rest) {
|
|
@@ -6127,7 +6146,7 @@ var GoogleAIPlatformInstrumentation = class extends _opentelemetry_instrumentati
|
|
|
6127
6146
|
spanType: "LLM"
|
|
6128
6147
|
});
|
|
6129
6148
|
const params = toGenAiParams(this, request);
|
|
6130
|
-
safely$1(() => setRequestAttributes$
|
|
6149
|
+
safely$1(() => setRequestAttributes$6(span, params, patchData.traceContent, VERTEX_AI_SYSTEM));
|
|
6131
6150
|
return Laminar.withSpan(span, async () => {
|
|
6132
6151
|
try {
|
|
6133
6152
|
const result = await original.call(this, request, ...rest);
|
|
@@ -6148,7 +6167,7 @@ var GoogleAIPlatformInstrumentation = class extends _opentelemetry_instrumentati
|
|
|
6148
6167
|
spanType: "LLM"
|
|
6149
6168
|
});
|
|
6150
6169
|
const params = toGenAiParams(this, request);
|
|
6151
|
-
safely$1(() => setRequestAttributes$
|
|
6170
|
+
safely$1(() => setRequestAttributes$6(span, params, patchData.traceContent, VERTEX_AI_SYSTEM));
|
|
6152
6171
|
let result;
|
|
6153
6172
|
try {
|
|
6154
6173
|
result = await Laminar.withSpan(span, () => original.call(this, request, ...rest));
|
|
@@ -6212,7 +6231,7 @@ var GoogleAIPlatformInstrumentation = class extends _opentelemetry_instrumentati
|
|
|
6212
6231
|
}
|
|
6213
6232
|
};
|
|
6214
6233
|
const setGenerateContentResponseAttributes = (span, response, requestModel, traceContent) => {
|
|
6215
|
-
setResponseAttributes$
|
|
6234
|
+
setResponseAttributes$6(span, response, traceContent);
|
|
6216
6235
|
if (!response?.modelVersion) safeSetAttribute$2(span, "gen_ai.response.model", requestModel);
|
|
6217
6236
|
};
|
|
6218
6237
|
//#endregion
|
|
@@ -6312,11 +6331,11 @@ var GoogleGenAiInstrumentation = class extends _opentelemetry_instrumentation.In
|
|
|
6312
6331
|
name: "gemini.generate_content",
|
|
6313
6332
|
spanType: "LLM"
|
|
6314
6333
|
});
|
|
6315
|
-
setRequestAttributes$
|
|
6334
|
+
setRequestAttributes$6(span, params, classPatchData.traceContent);
|
|
6316
6335
|
return Laminar.withSpan(span, async () => {
|
|
6317
6336
|
try {
|
|
6318
6337
|
const response = await originalGenerateContent(params);
|
|
6319
|
-
setResponseAttributes$
|
|
6338
|
+
setResponseAttributes$6(span, response, classPatchData.traceContent);
|
|
6320
6339
|
return response;
|
|
6321
6340
|
} catch (error) {
|
|
6322
6341
|
span.setAttribute("error.type", error.constructor?.name ?? "Error");
|
|
@@ -6331,7 +6350,7 @@ var GoogleGenAiInstrumentation = class extends _opentelemetry_instrumentation.In
|
|
|
6331
6350
|
name: "gemini.generate_content_stream",
|
|
6332
6351
|
spanType: "LLM"
|
|
6333
6352
|
});
|
|
6334
|
-
setRequestAttributes$
|
|
6353
|
+
setRequestAttributes$6(span, params, classPatchData.traceContent);
|
|
6335
6354
|
try {
|
|
6336
6355
|
return wrapStreamingResponse(span, await originalGenerateContentStream(params), classPatchData.traceContent);
|
|
6337
6356
|
} catch (error) {
|
|
@@ -6489,6 +6508,1053 @@ var KernelInstrumentation = class extends _opentelemetry_instrumentation.Instrum
|
|
|
6489
6508
|
this._unwrap(moduleExports.Kernel.prototype, "app");
|
|
6490
6509
|
}
|
|
6491
6510
|
};
|
|
6511
|
+
//#endregion
|
|
6512
|
+
//#region src/opentelemetry-lib/instrumentation/langchain/span-utils.ts
|
|
6513
|
+
const INPUT_MESSAGES$1 = "gen_ai.input.messages";
|
|
6514
|
+
const OUTPUT_MESSAGES$1 = "gen_ai.output.messages";
|
|
6515
|
+
const ROLE_BY_MESSAGE_TYPE = {
|
|
6516
|
+
human: "user",
|
|
6517
|
+
system: "system",
|
|
6518
|
+
ai: "assistant",
|
|
6519
|
+
tool: "tool",
|
|
6520
|
+
function: "tool"
|
|
6521
|
+
};
|
|
6522
|
+
const FINISH_REASON_MAP = {
|
|
6523
|
+
stop: "stop",
|
|
6524
|
+
length: "length",
|
|
6525
|
+
tool_calls: "tool_call",
|
|
6526
|
+
function_call: "tool_call",
|
|
6527
|
+
content_filter: "content_filter",
|
|
6528
|
+
end_turn: "stop",
|
|
6529
|
+
stop_sequence: "stop",
|
|
6530
|
+
tool_use: "tool_call",
|
|
6531
|
+
max_tokens: "length"
|
|
6532
|
+
};
|
|
6533
|
+
const MODEL_KEYS = [
|
|
6534
|
+
"model",
|
|
6535
|
+
"model_name",
|
|
6536
|
+
"model_id",
|
|
6537
|
+
"modelName"
|
|
6538
|
+
];
|
|
6539
|
+
const isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
6540
|
+
const asRecord = (value) => isRecord(value) ? value : {};
|
|
6541
|
+
const isInt = (value) => typeof value === "number" && Number.isInteger(value);
|
|
6542
|
+
/**
|
|
6543
|
+
* `JSON.stringify` that never throws: cycles become `"[Circular]"` and bigints
|
|
6544
|
+
* strings.
|
|
6545
|
+
*/
|
|
6546
|
+
const toJson$1 = (value) => {
|
|
6547
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
6548
|
+
try {
|
|
6549
|
+
return JSON.stringify(value, (_key, item) => {
|
|
6550
|
+
if (typeof item === "bigint") return item.toString();
|
|
6551
|
+
if (item !== null && typeof item === "object") {
|
|
6552
|
+
if (seen.has(item)) return "[Circular]";
|
|
6553
|
+
seen.add(item);
|
|
6554
|
+
}
|
|
6555
|
+
return item;
|
|
6556
|
+
}) ?? "null";
|
|
6557
|
+
} catch {
|
|
6558
|
+
return String(value);
|
|
6559
|
+
}
|
|
6560
|
+
};
|
|
6561
|
+
const maybeJson = (value) => {
|
|
6562
|
+
if (typeof value !== "string") return value;
|
|
6563
|
+
try {
|
|
6564
|
+
return JSON.parse(value);
|
|
6565
|
+
} catch {
|
|
6566
|
+
return value;
|
|
6567
|
+
}
|
|
6568
|
+
};
|
|
6569
|
+
const setIfPresent = (span, key, value) => {
|
|
6570
|
+
if (value === void 0 || value === null) return;
|
|
6571
|
+
if (typeof value === "string" && value.length === 0) return;
|
|
6572
|
+
span.setAttribute(key, value);
|
|
6573
|
+
};
|
|
6574
|
+
const messageType = (message) => {
|
|
6575
|
+
const type = message?.type ?? message?._getType?.() ?? message?.getType?.();
|
|
6576
|
+
return typeof type === "string" ? type : "";
|
|
6577
|
+
};
|
|
6578
|
+
const messageRole = (type) => ROLE_BY_MESSAGE_TYPE[type] ?? (type || "unknown");
|
|
6579
|
+
/**
|
|
6580
|
+
* Convert LangChain message content (string or list of blocks) into GenAI
|
|
6581
|
+
* parts.
|
|
6582
|
+
*/
|
|
6583
|
+
const contentToParts = (content) => {
|
|
6584
|
+
if (typeof content === "string") return content ? [{
|
|
6585
|
+
type: "text",
|
|
6586
|
+
content
|
|
6587
|
+
}] : [];
|
|
6588
|
+
if (!Array.isArray(content)) return content ? [{
|
|
6589
|
+
type: "text",
|
|
6590
|
+
content: String(content)
|
|
6591
|
+
}] : [];
|
|
6592
|
+
const parts = [];
|
|
6593
|
+
for (const block of content) {
|
|
6594
|
+
if (typeof block === "string") {
|
|
6595
|
+
if (block) parts.push({
|
|
6596
|
+
type: "text",
|
|
6597
|
+
content: block
|
|
6598
|
+
});
|
|
6599
|
+
continue;
|
|
6600
|
+
}
|
|
6601
|
+
if (!isRecord(block)) {
|
|
6602
|
+
parts.push({
|
|
6603
|
+
type: "text",
|
|
6604
|
+
content: String(block)
|
|
6605
|
+
});
|
|
6606
|
+
continue;
|
|
6607
|
+
}
|
|
6608
|
+
if (block.type === "text") {
|
|
6609
|
+
if (block.text) parts.push({
|
|
6610
|
+
type: "text",
|
|
6611
|
+
content: block.text
|
|
6612
|
+
});
|
|
6613
|
+
} else if (block.type === "image_url") {
|
|
6614
|
+
const url = isRecord(block.image_url) ? block.image_url.url : block.image_url;
|
|
6615
|
+
if (url) parts.push({
|
|
6616
|
+
type: "uri",
|
|
6617
|
+
modality: "image",
|
|
6618
|
+
uri: url
|
|
6619
|
+
});
|
|
6620
|
+
} else if (block.type === "image" && block.url) parts.push({
|
|
6621
|
+
type: "uri",
|
|
6622
|
+
modality: "image",
|
|
6623
|
+
uri: block.url
|
|
6624
|
+
});
|
|
6625
|
+
else if (block.type === "image") parts.push({
|
|
6626
|
+
type: "blob",
|
|
6627
|
+
modality: "image",
|
|
6628
|
+
mime_type: block.mime_type || block.mimeType || block.media_type || "",
|
|
6629
|
+
content: block.data || block.base64 || ""
|
|
6630
|
+
});
|
|
6631
|
+
else parts.push(block);
|
|
6632
|
+
}
|
|
6633
|
+
return parts;
|
|
6634
|
+
};
|
|
6635
|
+
const toolCallsToParts = (toolCalls) => {
|
|
6636
|
+
if (!Array.isArray(toolCalls)) return [];
|
|
6637
|
+
const parts = [];
|
|
6638
|
+
for (const toolCall of toolCalls) {
|
|
6639
|
+
if (!isRecord(toolCall)) continue;
|
|
6640
|
+
const fn = asRecord(toolCall.function);
|
|
6641
|
+
const part = {
|
|
6642
|
+
type: "tool_call",
|
|
6643
|
+
id: toolCall.id || "",
|
|
6644
|
+
name: toolCall.name || fn.name || ""
|
|
6645
|
+
};
|
|
6646
|
+
const args = toolCall.args ?? fn.arguments;
|
|
6647
|
+
if (args !== void 0 && args !== null) part.arguments = maybeJson(args);
|
|
6648
|
+
parts.push(part);
|
|
6649
|
+
}
|
|
6650
|
+
return parts;
|
|
6651
|
+
};
|
|
6652
|
+
const messageToolCalls = (message) => {
|
|
6653
|
+
if (Array.isArray(message?.tool_calls) && message.tool_calls.length > 0) return message.tool_calls;
|
|
6654
|
+
return message?.additional_kwargs?.tool_calls;
|
|
6655
|
+
};
|
|
6656
|
+
const messageToDict = (message) => {
|
|
6657
|
+
const role = messageRole(messageType(message));
|
|
6658
|
+
const toolCallId = message?.tool_call_id;
|
|
6659
|
+
if (role === "tool" && toolCallId) return {
|
|
6660
|
+
role,
|
|
6661
|
+
parts: [{
|
|
6662
|
+
type: "tool_call_response",
|
|
6663
|
+
id: toolCallId,
|
|
6664
|
+
response: message.content
|
|
6665
|
+
}]
|
|
6666
|
+
};
|
|
6667
|
+
const parts = [...contentToParts(message?.content), ...toolCallsToParts(messageToolCalls(message))];
|
|
6668
|
+
const functionCall = message?.additional_kwargs?.function_call;
|
|
6669
|
+
if (isRecord(functionCall)) parts.push({
|
|
6670
|
+
type: "tool_call",
|
|
6671
|
+
id: "",
|
|
6672
|
+
name: functionCall.name || "",
|
|
6673
|
+
arguments: maybeJson(functionCall.arguments)
|
|
6674
|
+
});
|
|
6675
|
+
return {
|
|
6676
|
+
role,
|
|
6677
|
+
parts
|
|
6678
|
+
};
|
|
6679
|
+
};
|
|
6680
|
+
const firstModel = (...sources) => {
|
|
6681
|
+
for (const source of sources) for (const key of MODEL_KEYS) {
|
|
6682
|
+
const model = source[key];
|
|
6683
|
+
if (typeof model === "string" && model) return model;
|
|
6684
|
+
}
|
|
6685
|
+
};
|
|
6686
|
+
/**
|
|
6687
|
+
* Record the request model and sampling params. Returns the request model.
|
|
6688
|
+
*/
|
|
6689
|
+
const setRequestAttributes$3 = (span, serialized, metadata, extraParams, traceContent) => {
|
|
6690
|
+
const invocationParams = asRecord(extraParams?.invocation_params);
|
|
6691
|
+
const nested = asRecord(invocationParams.params);
|
|
6692
|
+
const params = Object.keys(nested).length > 0 ? nested : invocationParams;
|
|
6693
|
+
const serializedKwargs = asRecord(serialized?.kwargs);
|
|
6694
|
+
let model = firstModel(params, invocationParams, serializedKwargs);
|
|
6695
|
+
if (model === void 0) {
|
|
6696
|
+
const lsModelName = metadata?.ls_model_name;
|
|
6697
|
+
model = typeof lsModelName === "string" && lsModelName ? lsModelName : void 0;
|
|
6698
|
+
}
|
|
6699
|
+
setIfPresent(span, "gen_ai.request.model", model);
|
|
6700
|
+
const param = (...keys) => {
|
|
6701
|
+
for (const source of [params, serializedKwargs]) for (const key of keys) if (source[key] !== void 0 && source[key] !== null) return source[key];
|
|
6702
|
+
};
|
|
6703
|
+
const maxTokens = param("max_tokens", "max_completion_tokens", "max_new_tokens", "maxTokens");
|
|
6704
|
+
const temperature = param("temperature");
|
|
6705
|
+
const topP = param("top_p", "topP");
|
|
6706
|
+
if (isInt(maxTokens)) span.setAttribute("gen_ai.request.max_tokens", maxTokens);
|
|
6707
|
+
if (typeof temperature === "number") span.setAttribute("gen_ai.request.temperature", temperature);
|
|
6708
|
+
if (typeof topP === "number") span.setAttribute("gen_ai.request.top_p", topP);
|
|
6709
|
+
const tools = params.tools || params.functions;
|
|
6710
|
+
if (traceContent && Array.isArray(tools) && tools.length > 0) {
|
|
6711
|
+
const definitions = tools.map((tool) => {
|
|
6712
|
+
const record = asRecord(tool);
|
|
6713
|
+
const fn = isRecord(record.function) ? record.function : record;
|
|
6714
|
+
const definition = { name: fn.name };
|
|
6715
|
+
if (fn.description) definition.description = fn.description;
|
|
6716
|
+
const parameters = fn.parameters || record.input_schema;
|
|
6717
|
+
if (parameters) definition.parameters = parameters;
|
|
6718
|
+
return definition;
|
|
6719
|
+
});
|
|
6720
|
+
span.setAttribute("gen_ai.tool.definitions", toJson$1(definitions));
|
|
6721
|
+
}
|
|
6722
|
+
return model;
|
|
6723
|
+
};
|
|
6724
|
+
const setChatRequest$1 = (span, messages, traceContent) => {
|
|
6725
|
+
if (!traceContent) return;
|
|
6726
|
+
const inputMessages = (messages ?? []).flatMap((batch) => (batch ?? []).map(messageToDict));
|
|
6727
|
+
if (inputMessages.length > 0) span.setAttribute(INPUT_MESSAGES$1, toJson$1(inputMessages));
|
|
6728
|
+
};
|
|
6729
|
+
const setCompletionRequest$1 = (span, prompts, traceContent) => {
|
|
6730
|
+
if (!traceContent) return;
|
|
6731
|
+
const inputMessages = (prompts ?? []).map((prompt) => ({
|
|
6732
|
+
role: "user",
|
|
6733
|
+
parts: [{
|
|
6734
|
+
type: "text",
|
|
6735
|
+
content: prompt
|
|
6736
|
+
}]
|
|
6737
|
+
}));
|
|
6738
|
+
if (inputMessages.length > 0) span.setAttribute(INPUT_MESSAGES$1, toJson$1(inputMessages));
|
|
6739
|
+
};
|
|
6740
|
+
const allGenerations = (response) => Array.isArray(response?.generations) ? response.generations.flatMap((batch) => Array.isArray(batch) ? batch : []) : [];
|
|
6741
|
+
const setUsage = (span, response) => {
|
|
6742
|
+
let inputTokens = 0;
|
|
6743
|
+
let outputTokens = 0;
|
|
6744
|
+
let cacheReadTokens;
|
|
6745
|
+
let cacheCreationTokens;
|
|
6746
|
+
let found = false;
|
|
6747
|
+
for (const generation of allGenerations(response)) {
|
|
6748
|
+
const usage = asRecord(generation?.message?.usage_metadata);
|
|
6749
|
+
if (Object.keys(usage).length === 0) continue;
|
|
6750
|
+
found = true;
|
|
6751
|
+
inputTokens += isInt(usage.input_tokens) ? usage.input_tokens : 0;
|
|
6752
|
+
outputTokens += isInt(usage.output_tokens) ? usage.output_tokens : 0;
|
|
6753
|
+
const details = asRecord(usage.input_token_details);
|
|
6754
|
+
if (isInt(details.cache_read)) cacheReadTokens = (cacheReadTokens ?? 0) + details.cache_read;
|
|
6755
|
+
if (isInt(details.cache_creation)) cacheCreationTokens = (cacheCreationTokens ?? 0) + details.cache_creation;
|
|
6756
|
+
}
|
|
6757
|
+
if (!found) {
|
|
6758
|
+
const llmOutput = asRecord(response?.llmOutput);
|
|
6759
|
+
const tokenUsage = asRecord(llmOutput.tokenUsage ?? llmOutput.token_usage ?? llmOutput.usage);
|
|
6760
|
+
if (Object.keys(tokenUsage).length === 0) return;
|
|
6761
|
+
const pick = (...keys) => {
|
|
6762
|
+
for (const key of keys) if (isInt(tokenUsage[key]) && tokenUsage[key] !== 0) return tokenUsage[key];
|
|
6763
|
+
return 0;
|
|
6764
|
+
};
|
|
6765
|
+
inputTokens = pick("promptTokens", "prompt_tokens", "input_tokens", "input_token_count");
|
|
6766
|
+
outputTokens = pick("completionTokens", "completion_tokens", "output_tokens", "generated_token_count");
|
|
6767
|
+
}
|
|
6768
|
+
span.setAttribute("gen_ai.usage.input_tokens", inputTokens);
|
|
6769
|
+
span.setAttribute("gen_ai.usage.output_tokens", outputTokens);
|
|
6770
|
+
span.setAttribute("llm.usage.total_tokens", inputTokens + outputTokens);
|
|
6771
|
+
setIfPresent(span, "gen_ai.usage.cache_read_input_tokens", cacheReadTokens);
|
|
6772
|
+
setIfPresent(span, "gen_ai.usage.cache_creation_input_tokens", cacheCreationTokens);
|
|
6773
|
+
};
|
|
6774
|
+
const responseModelAndId = (response) => {
|
|
6775
|
+
const llmOutput = asRecord(response?.llmOutput);
|
|
6776
|
+
let model = firstModel(llmOutput);
|
|
6777
|
+
let id = llmOutput.id;
|
|
6778
|
+
for (const generation of allGenerations(response)) {
|
|
6779
|
+
const message = generation?.message;
|
|
6780
|
+
if (model === void 0) model = firstModel(asRecord(message?.response_metadata));
|
|
6781
|
+
if (id === void 0 || id === null) id = message?.id;
|
|
6782
|
+
}
|
|
6783
|
+
return {
|
|
6784
|
+
model,
|
|
6785
|
+
id: typeof id === "string" && id ? id : void 0
|
|
6786
|
+
};
|
|
6787
|
+
};
|
|
6788
|
+
const finishReasonOf = (generation) => {
|
|
6789
|
+
const info = asRecord(generation?.generationInfo);
|
|
6790
|
+
const metadata = asRecord(generation?.message?.response_metadata);
|
|
6791
|
+
const raw = info.finish_reason || info.stop_reason || metadata.finish_reason || metadata.stop_reason;
|
|
6792
|
+
return typeof raw === "string" ? FINISH_REASON_MAP[raw] ?? raw : void 0;
|
|
6793
|
+
};
|
|
6794
|
+
const setResponseAttributes$3 = (span, response, requestModel, traceContent) => {
|
|
6795
|
+
const { model, id } = responseModelAndId(response);
|
|
6796
|
+
setIfPresent(span, "gen_ai.response.model", model ?? requestModel);
|
|
6797
|
+
if (requestModel === void 0) setIfPresent(span, "gen_ai.request.model", model);
|
|
6798
|
+
setIfPresent(span, "gen_ai.response.id", id);
|
|
6799
|
+
setUsage(span, response);
|
|
6800
|
+
const outputMessages = [];
|
|
6801
|
+
const finishReasons = [];
|
|
6802
|
+
for (const generation of allGenerations(response)) {
|
|
6803
|
+
const finishReason = finishReasonOf(generation);
|
|
6804
|
+
if (finishReason && !finishReasons.includes(finishReason)) finishReasons.push(finishReason);
|
|
6805
|
+
if (!traceContent) continue;
|
|
6806
|
+
const message = generation?.message;
|
|
6807
|
+
const outputMessage = message && typeof message === "object" ? messageToDict(message) : {
|
|
6808
|
+
role: "assistant",
|
|
6809
|
+
parts: contentToParts(generation?.text)
|
|
6810
|
+
};
|
|
6811
|
+
outputMessage.finish_reason = finishReason ?? "";
|
|
6812
|
+
outputMessages.push(outputMessage);
|
|
6813
|
+
}
|
|
6814
|
+
if (finishReasons.length > 0) span.setAttribute("gen_ai.response.finish_reasons", finishReasons);
|
|
6815
|
+
if (outputMessages.length > 0) span.setAttribute(OUTPUT_MESSAGES$1, toJson$1(outputMessages));
|
|
6816
|
+
};
|
|
6817
|
+
/**
|
|
6818
|
+
* Return plain-data metadata as is, or undefined for anything else.
|
|
6819
|
+
*
|
|
6820
|
+
* Class instances are dropped rather than stringified: a model, client or
|
|
6821
|
+
* config object routinely carries credentials the caller never meant to
|
|
6822
|
+
* export.
|
|
6823
|
+
*/
|
|
6824
|
+
const metadataValue = (value) => {
|
|
6825
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
|
|
6826
|
+
if (value instanceof Date) return Number.isNaN(value.getTime()) ? void 0 : value.toISOString();
|
|
6827
|
+
if (Array.isArray(value)) return value.map(metadataValue).filter((item) => item !== void 0);
|
|
6828
|
+
if (isRecord(value)) {
|
|
6829
|
+
const proto = Object.getPrototypeOf(value);
|
|
6830
|
+
if (proto !== Object.prototype && proto !== null) return void 0;
|
|
6831
|
+
const kept = Object.fromEntries(Object.entries(value).map(([key, item]) => [key, metadataValue(item)]).filter(([, item]) => item !== void 0));
|
|
6832
|
+
return Object.keys(kept).length > 0 ? kept : void 0;
|
|
6833
|
+
}
|
|
6834
|
+
};
|
|
6835
|
+
const sanitizeMetadata = (metadata) => {
|
|
6836
|
+
if (!isRecord(metadata)) return {};
|
|
6837
|
+
return Object.fromEntries(Object.entries(metadata).map(([key, value]) => [key, metadataValue(value)]).filter(([, value]) => value !== void 0));
|
|
6838
|
+
};
|
|
6839
|
+
const retrieverOutput = (documents) => {
|
|
6840
|
+
if (!Array.isArray(documents)) return [];
|
|
6841
|
+
return documents.map((document) => {
|
|
6842
|
+
const pageContent = document?.pageContent ?? document?.page_content;
|
|
6843
|
+
if (pageContent === void 0 || pageContent === null) return document;
|
|
6844
|
+
return {
|
|
6845
|
+
page_content: pageContent,
|
|
6846
|
+
metadata: document?.metadata ?? {}
|
|
6847
|
+
};
|
|
6848
|
+
});
|
|
6849
|
+
};
|
|
6850
|
+
//#endregion
|
|
6851
|
+
//#region src/opentelemetry-lib/instrumentation/langchain/vendor-detection.ts
|
|
6852
|
+
const DEFAULT_VENDOR = "langchain";
|
|
6853
|
+
/**
|
|
6854
|
+
* Lower-cased class-name substrings → `gen_ai.system` vendor, in priority
|
|
6855
|
+
* order (`AzureChatOpenAI` must match azure before openai).
|
|
6856
|
+
*/
|
|
6857
|
+
const VENDOR_RULES = [
|
|
6858
|
+
[["azure"], "azure.ai.openai"],
|
|
6859
|
+
[["openai"], "openai"],
|
|
6860
|
+
[["bedrock", "aws"], "aws.bedrock"],
|
|
6861
|
+
[["anthropic"], "anthropic"],
|
|
6862
|
+
[["vertex"], "gcp.vertex_ai"],
|
|
6863
|
+
[["google", "gemini"], "gcp.gen_ai"],
|
|
6864
|
+
[["cohere"], "cohere"],
|
|
6865
|
+
[["huggingface"], "hugging_face"],
|
|
6866
|
+
[["ollama"], "ollama"],
|
|
6867
|
+
[["together"], "together_ai"],
|
|
6868
|
+
[["replicate"], "replicate"],
|
|
6869
|
+
[["fireworks"], "fireworks"],
|
|
6870
|
+
[["groq"], "groq"],
|
|
6871
|
+
[["mistral"], "mistral_ai"]
|
|
6872
|
+
];
|
|
6873
|
+
/**
|
|
6874
|
+
* Map a LangChain model class name (e.g. `ChatOpenAI`) onto the
|
|
6875
|
+
* `gen_ai.system` vendor string, or `"langchain"` when unknown.
|
|
6876
|
+
*/
|
|
6877
|
+
const detectVendorFromClass = (className) => {
|
|
6878
|
+
if (!className) return DEFAULT_VENDOR;
|
|
6879
|
+
const lower = className.toLowerCase();
|
|
6880
|
+
for (const [patterns, vendor] of VENDOR_RULES) if (patterns.some((pattern) => lower.includes(pattern))) return vendor;
|
|
6881
|
+
return DEFAULT_VENDOR;
|
|
6882
|
+
};
|
|
6883
|
+
//#endregion
|
|
6884
|
+
//#region src/opentelemetry-lib/instrumentation/langchain/callback-handler.ts
|
|
6885
|
+
const logger$18 = require_utils.initializeLogger();
|
|
6886
|
+
const HANDLER_NAME = "laminar_callback_handler";
|
|
6887
|
+
/**
|
|
6888
|
+
* Callback handlers must never break the user's chain.
|
|
6889
|
+
*/
|
|
6890
|
+
const dontThrow = (fn) => {
|
|
6891
|
+
try {
|
|
6892
|
+
fn();
|
|
6893
|
+
} catch (error) {
|
|
6894
|
+
logger$18.debug(`Failed to record LangChain run: ${String(error)}`);
|
|
6895
|
+
}
|
|
6896
|
+
};
|
|
6897
|
+
const className = (serialized) => {
|
|
6898
|
+
const id = serialized?.id;
|
|
6899
|
+
if (Array.isArray(id) && id.length > 0) return String(id[id.length - 1]);
|
|
6900
|
+
return typeof id === "string" ? id : "";
|
|
6901
|
+
};
|
|
6902
|
+
const runNameOf = (serialized, runName) => {
|
|
6903
|
+
for (const name of [
|
|
6904
|
+
runName,
|
|
6905
|
+
serialized?.kwargs?.name,
|
|
6906
|
+
serialized?.name
|
|
6907
|
+
]) if (typeof name === "string" && name) return name;
|
|
6908
|
+
return className(serialized) || "unknown";
|
|
6909
|
+
};
|
|
6910
|
+
/**
|
|
6911
|
+
* LangGraph's `configurable.thread_id`, the conversation id.
|
|
6912
|
+
*/
|
|
6913
|
+
const threadIdOf = (metadata, extra) => {
|
|
6914
|
+
const threadId = metadata?.thread_id ?? extra?.config?.configurable?.thread_id;
|
|
6915
|
+
return threadId === void 0 || threadId === null ? void 0 : String(threadId);
|
|
6916
|
+
};
|
|
6917
|
+
/**
|
|
6918
|
+
* Drop what only applies to the context a callback fired in (an open LLM
|
|
6919
|
+
* call's marker and its suppression) before parenting a new run from it.
|
|
6920
|
+
*/
|
|
6921
|
+
const cleanContext = (ctx) => (0, _opentelemetry_core.unsuppressTracing)(ctx).deleteValue(LLM_CALL_KEY);
|
|
6922
|
+
/**
|
|
6923
|
+
* Records LangChain runs as Laminar spans.
|
|
6924
|
+
*
|
|
6925
|
+
* A single instance is injected into every LangChain `CallbackManager`, so all
|
|
6926
|
+
* state is keyed by LangChain's `runId`. Callbacks only start and end spans:
|
|
6927
|
+
* JavaScript callbacks cannot change the context of the code they observe, so
|
|
6928
|
+
* the instrumentation wrappers read `contextFor(runId)` to run user code (a
|
|
6929
|
+
* lambda, a tool, a graph node) and provider SDK calls under the right span.
|
|
6930
|
+
*
|
|
6931
|
+
* Duck-types LangChain's `BaseCallbackHandler` (`name`, `awaitHandlers`,
|
|
6932
|
+
* `copy`), as `@langchain/core` is not a runtime dependency of this package.
|
|
6933
|
+
*/
|
|
6934
|
+
var LaminarCallbackHandler = class {
|
|
6935
|
+
constructor(traceContent) {
|
|
6936
|
+
this.name = HANDLER_NAME;
|
|
6937
|
+
this.awaitHandlers = true;
|
|
6938
|
+
this.raiseError = false;
|
|
6939
|
+
this.ignoreLLM = false;
|
|
6940
|
+
this.ignoreChain = false;
|
|
6941
|
+
this.ignoreAgent = false;
|
|
6942
|
+
this.ignoreRetriever = false;
|
|
6943
|
+
this.ignoreCustomEvent = true;
|
|
6944
|
+
this.lc_serializable = false;
|
|
6945
|
+
this.takeTopology = () => void 0;
|
|
6946
|
+
this.runs = /* @__PURE__ */ new Map();
|
|
6947
|
+
this.handedOff = /* @__PURE__ */ new Map();
|
|
6948
|
+
this.traceContent = traceContent;
|
|
6949
|
+
}
|
|
6950
|
+
copy() {
|
|
6951
|
+
return this;
|
|
6952
|
+
}
|
|
6953
|
+
/**
|
|
6954
|
+
* Context of an open run (or of a handed-off LLM run's parent), for code
|
|
6955
|
+
* that runs under it.
|
|
6956
|
+
*/
|
|
6957
|
+
contextFor(runId) {
|
|
6958
|
+
if (!runId) return void 0;
|
|
6959
|
+
return this.runs.get(runId)?.context ?? this.handedOff.get(runId)?.context;
|
|
6960
|
+
}
|
|
6961
|
+
handleChainStart(chain, inputs, runId, parentRunId, tags, metadata, _runType, runName, extra) {
|
|
6962
|
+
dontThrow(() => {
|
|
6963
|
+
const name = runNameOf(chain, runName);
|
|
6964
|
+
const isRoot = !parentRunId || !this.runs.has(parentRunId) && !this.handedOff.has(parentRunId);
|
|
6965
|
+
const attributes = {};
|
|
6966
|
+
let spanName;
|
|
6967
|
+
if (isRoot) {
|
|
6968
|
+
spanName = `${name}.workflow`;
|
|
6969
|
+
attributes["gen_ai.operation.name"] = "invoke_agent";
|
|
6970
|
+
attributes["gen_ai.agent.name"] = name;
|
|
6971
|
+
attributes["gen_ai.agent.id"] = String(runId);
|
|
6972
|
+
} else {
|
|
6973
|
+
spanName = `execute_task ${name}`;
|
|
6974
|
+
attributes["gen_ai.operation.name"] = "execute_task";
|
|
6975
|
+
}
|
|
6976
|
+
const threadId = threadIdOf(metadata, extra);
|
|
6977
|
+
if (threadId) attributes["gen_ai.conversation.id"] = threadId;
|
|
6978
|
+
const topology = this.takeTopology();
|
|
6979
|
+
if (topology && isRoot) for (const [key, value] of Object.entries(topology)) attributes[`lmnr.association.properties.${key}`] = value;
|
|
6980
|
+
const span = this.startRun(runId, parentRunId, spanName, {
|
|
6981
|
+
attributes,
|
|
6982
|
+
tags,
|
|
6983
|
+
metadata
|
|
6984
|
+
});
|
|
6985
|
+
if (span && this.traceContent) span.setInput(toJson$1(inputs));
|
|
6986
|
+
});
|
|
6987
|
+
}
|
|
6988
|
+
handleChainEnd(outputs, runId) {
|
|
6989
|
+
dontThrow(() => {
|
|
6990
|
+
try {
|
|
6991
|
+
this.setOutput(runId, outputs);
|
|
6992
|
+
} finally {
|
|
6993
|
+
this.endRun(runId);
|
|
6994
|
+
}
|
|
6995
|
+
});
|
|
6996
|
+
}
|
|
6997
|
+
handleChainError(error, runId) {
|
|
6998
|
+
dontThrow(() => this.handleError(error, runId));
|
|
6999
|
+
}
|
|
7000
|
+
handleChatModelStart(llm, messages, runId, parentRunId, extraParams, tags, metadata, runName) {
|
|
7001
|
+
dontThrow(() => this.startLlm(llm, messages, "chat", runId, parentRunId, {
|
|
7002
|
+
extraParams,
|
|
7003
|
+
tags,
|
|
7004
|
+
metadata,
|
|
7005
|
+
runName
|
|
7006
|
+
}));
|
|
7007
|
+
}
|
|
7008
|
+
handleLLMStart(llm, prompts, runId, parentRunId, extraParams, tags, metadata, runName) {
|
|
7009
|
+
dontThrow(() => this.startLlm(llm, prompts, "text_completion", runId, parentRunId, {
|
|
7010
|
+
extraParams,
|
|
7011
|
+
tags,
|
|
7012
|
+
metadata,
|
|
7013
|
+
runName
|
|
7014
|
+
}));
|
|
7015
|
+
}
|
|
7016
|
+
handleLLMEnd(output, runId) {
|
|
7017
|
+
dontThrow(() => {
|
|
7018
|
+
try {
|
|
7019
|
+
const run = this.runs.get(runId);
|
|
7020
|
+
if (run) setResponseAttributes$3(run.span, output, run.requestModel, this.traceContent);
|
|
7021
|
+
else this.recordUnrecordedHandoff(runId, (span, requestModel) => setResponseAttributes$3(span, output, requestModel, this.traceContent));
|
|
7022
|
+
} finally {
|
|
7023
|
+
this.endRun(runId);
|
|
7024
|
+
}
|
|
7025
|
+
});
|
|
7026
|
+
}
|
|
7027
|
+
handleLLMError(error, runId) {
|
|
7028
|
+
dontThrow(() => this.handleError(error, runId));
|
|
7029
|
+
}
|
|
7030
|
+
handleToolStart(tool, input, runId, parentRunId, tags, metadata, runName, toolCallId) {
|
|
7031
|
+
dontThrow(() => {
|
|
7032
|
+
const name = runNameOf(tool, runName);
|
|
7033
|
+
const attributes = {
|
|
7034
|
+
"gen_ai.operation.name": "execute_tool",
|
|
7035
|
+
"gen_ai.tool.name": name,
|
|
7036
|
+
"gen_ai.tool.type": "function"
|
|
7037
|
+
};
|
|
7038
|
+
const description = tool?.description ?? tool?.kwargs?.description;
|
|
7039
|
+
if (typeof description === "string" && description) attributes["gen_ai.tool.description"] = description;
|
|
7040
|
+
if (typeof toolCallId === "string" && toolCallId) attributes["gen_ai.tool.call.id"] = toolCallId;
|
|
7041
|
+
const span = this.startRun(runId, parentRunId, `execute_tool ${name}`, {
|
|
7042
|
+
spanType: "TOOL",
|
|
7043
|
+
attributes,
|
|
7044
|
+
tags,
|
|
7045
|
+
metadata
|
|
7046
|
+
});
|
|
7047
|
+
if (span && this.traceContent) span.setInput(toJson$1(parseJsonObject(input)));
|
|
7048
|
+
});
|
|
7049
|
+
}
|
|
7050
|
+
handleToolEnd(output, runId) {
|
|
7051
|
+
dontThrow(() => {
|
|
7052
|
+
try {
|
|
7053
|
+
this.setOutput(runId, output);
|
|
7054
|
+
} finally {
|
|
7055
|
+
this.endRun(runId);
|
|
7056
|
+
}
|
|
7057
|
+
});
|
|
7058
|
+
}
|
|
7059
|
+
handleToolError(error, runId) {
|
|
7060
|
+
dontThrow(() => this.handleError(error, runId));
|
|
7061
|
+
}
|
|
7062
|
+
handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata, runName) {
|
|
7063
|
+
dontThrow(() => {
|
|
7064
|
+
const name = runNameOf(retriever, runName);
|
|
7065
|
+
const span = this.startRun(runId, parentRunId, `vector_db_retrieve ${name}`, {
|
|
7066
|
+
attributes: { "gen_ai.operation.name": "vector_db_retrieve" },
|
|
7067
|
+
tags,
|
|
7068
|
+
metadata
|
|
7069
|
+
});
|
|
7070
|
+
if (span && this.traceContent) span.setInput(toJson$1(query));
|
|
7071
|
+
});
|
|
7072
|
+
}
|
|
7073
|
+
handleRetrieverEnd(documents, runId) {
|
|
7074
|
+
dontThrow(() => {
|
|
7075
|
+
try {
|
|
7076
|
+
this.setOutput(runId, retrieverOutput(documents));
|
|
7077
|
+
} finally {
|
|
7078
|
+
this.endRun(runId);
|
|
7079
|
+
}
|
|
7080
|
+
});
|
|
7081
|
+
}
|
|
7082
|
+
handleRetrieverError(error, runId) {
|
|
7083
|
+
dontThrow(() => this.handleError(error, runId));
|
|
7084
|
+
}
|
|
7085
|
+
parentContext(parentRunId) {
|
|
7086
|
+
return cleanContext(this.contextFor(parentRunId) ?? LaminarContextManager.getContext());
|
|
7087
|
+
}
|
|
7088
|
+
startRun(runId, parentRunId, name, { spanType = "DEFAULT", attributes, tags, metadata, startTime }) {
|
|
7089
|
+
const active = _opentelemetry_api.context.active();
|
|
7090
|
+
if ((0, _opentelemetry_core.isTracingSuppressed)(active) && active.getValue(LLM_CALL_KEY)?.mode !== "own") return;
|
|
7091
|
+
const parentContext = this.parentContext(parentRunId);
|
|
7092
|
+
const span = this.startSpan(name, spanType, parentContext, {
|
|
7093
|
+
attributes,
|
|
7094
|
+
tags,
|
|
7095
|
+
metadata,
|
|
7096
|
+
startTime
|
|
7097
|
+
});
|
|
7098
|
+
const run = {
|
|
7099
|
+
span,
|
|
7100
|
+
context: _opentelemetry_api.trace.setSpan(LaminarContextManager.setAssociationProperties(span, parentContext), span),
|
|
7101
|
+
children: []
|
|
7102
|
+
};
|
|
7103
|
+
if (parentRunId) this.runs.get(parentRunId)?.children.push(runId);
|
|
7104
|
+
const stale = this.runs.get(runId);
|
|
7105
|
+
if (stale) {
|
|
7106
|
+
this.runs.delete(runId);
|
|
7107
|
+
stale.span.end();
|
|
7108
|
+
}
|
|
7109
|
+
this.runs.set(runId, run);
|
|
7110
|
+
return span;
|
|
7111
|
+
}
|
|
7112
|
+
startSpan(name, spanType, parentContext, { attributes, tags, metadata, startTime }) {
|
|
7113
|
+
const span = Laminar.startSpan({
|
|
7114
|
+
name,
|
|
7115
|
+
spanType,
|
|
7116
|
+
context: parentContext,
|
|
7117
|
+
startTime
|
|
7118
|
+
});
|
|
7119
|
+
if (attributes) span.setAttributes(attributes);
|
|
7120
|
+
if (tags && tags.length > 0) span.setAttribute("langchain.tags", tags);
|
|
7121
|
+
const sanitized = sanitizeMetadata(metadata);
|
|
7122
|
+
if (Object.keys(sanitized).length > 0) span.setAttribute("langchain.metadata", toJson$1(sanitized));
|
|
7123
|
+
return span;
|
|
7124
|
+
}
|
|
7125
|
+
startLlm(llm, input, operation, runId, parentRunId, { extraParams, tags, metadata, runName }) {
|
|
7126
|
+
const name = runNameOf(llm, runName);
|
|
7127
|
+
const call = _opentelemetry_api.context.active().getValue(LLM_CALL_KEY);
|
|
7128
|
+
if (call?.mode === "handoff") {
|
|
7129
|
+
this.handedOff.set(runId, {
|
|
7130
|
+
context: this.parentContext(parentRunId),
|
|
7131
|
+
call,
|
|
7132
|
+
name,
|
|
7133
|
+
operation,
|
|
7134
|
+
serialized: llm,
|
|
7135
|
+
input,
|
|
7136
|
+
extraParams,
|
|
7137
|
+
tags,
|
|
7138
|
+
metadata,
|
|
7139
|
+
startTime: (0, _opentelemetry_core.hrTime)()
|
|
7140
|
+
});
|
|
7141
|
+
if (parentRunId) this.runs.get(parentRunId)?.children.push(runId);
|
|
7142
|
+
return;
|
|
7143
|
+
}
|
|
7144
|
+
const span = this.startRun(runId, parentRunId, llmSpanName(name, operation), {
|
|
7145
|
+
spanType: "LLM",
|
|
7146
|
+
attributes: llmAttributes(llm, operation),
|
|
7147
|
+
tags,
|
|
7148
|
+
metadata
|
|
7149
|
+
});
|
|
7150
|
+
if (!span) return;
|
|
7151
|
+
const run = this.runs.get(runId);
|
|
7152
|
+
run.requestModel = this.setLlmRequest(span, {
|
|
7153
|
+
serialized: llm,
|
|
7154
|
+
input,
|
|
7155
|
+
operation,
|
|
7156
|
+
extraParams,
|
|
7157
|
+
metadata
|
|
7158
|
+
});
|
|
7159
|
+
}
|
|
7160
|
+
setLlmRequest(span, { serialized, input, operation, extraParams, metadata }) {
|
|
7161
|
+
const requestModel = setRequestAttributes$3(span, serialized, metadata, extraParams, this.traceContent);
|
|
7162
|
+
if (operation === "chat") setChatRequest$1(span, input, this.traceContent);
|
|
7163
|
+
else setCompletionRequest$1(span, input, this.traceContent);
|
|
7164
|
+
return requestModel;
|
|
7165
|
+
}
|
|
7166
|
+
/**
|
|
7167
|
+
* A handed-off LLM run whose provider instrumentation did not record the
|
|
7168
|
+
* call (it is disabled, or the integration bundles its own copy of the
|
|
7169
|
+
* provider SDK) gets its LangChain span after all, spanning the run.
|
|
7170
|
+
*/
|
|
7171
|
+
recordUnrecordedHandoff(runId, finish) {
|
|
7172
|
+
const pending = this.handedOff.get(runId);
|
|
7173
|
+
if (!pending || pending.call.recorded) return;
|
|
7174
|
+
const span = this.startSpan(llmSpanName(pending.name, pending.operation), "LLM", pending.context, {
|
|
7175
|
+
attributes: llmAttributes(pending.serialized, pending.operation),
|
|
7176
|
+
tags: pending.tags,
|
|
7177
|
+
metadata: pending.metadata,
|
|
7178
|
+
startTime: pending.startTime
|
|
7179
|
+
});
|
|
7180
|
+
try {
|
|
7181
|
+
finish(span, this.setLlmRequest(span, pending));
|
|
7182
|
+
} finally {
|
|
7183
|
+
span.end();
|
|
7184
|
+
}
|
|
7185
|
+
}
|
|
7186
|
+
setOutput(runId, output) {
|
|
7187
|
+
const run = this.runs.get(runId);
|
|
7188
|
+
if (run && this.traceContent) run.span.setOutput(toJson$1(output));
|
|
7189
|
+
}
|
|
7190
|
+
handleError(error, runId) {
|
|
7191
|
+
const run = this.runs.get(runId);
|
|
7192
|
+
if (!run) {
|
|
7193
|
+
try {
|
|
7194
|
+
this.recordUnrecordedHandoff(runId, (span) => markError(span, error));
|
|
7195
|
+
} finally {
|
|
7196
|
+
this.handedOff.delete(runId);
|
|
7197
|
+
}
|
|
7198
|
+
return;
|
|
7199
|
+
}
|
|
7200
|
+
try {
|
|
7201
|
+
markError(run.span, error);
|
|
7202
|
+
} finally {
|
|
7203
|
+
this.endRun(runId);
|
|
7204
|
+
}
|
|
7205
|
+
}
|
|
7206
|
+
endRun(runId) {
|
|
7207
|
+
this.handedOff.delete(runId);
|
|
7208
|
+
const run = this.runs.get(runId);
|
|
7209
|
+
if (!run) return;
|
|
7210
|
+
this.runs.delete(runId);
|
|
7211
|
+
for (const childId of run.children) this.endRun(childId);
|
|
7212
|
+
run.span.end();
|
|
7213
|
+
}
|
|
7214
|
+
};
|
|
7215
|
+
const llmSpanName = (name, operation) => `${name}.${operation === "chat" ? "chat" : "completion"}`;
|
|
7216
|
+
const llmAttributes = (serialized, operation) => {
|
|
7217
|
+
const vendor = detectVendorFromClass(className(serialized));
|
|
7218
|
+
return {
|
|
7219
|
+
"gen_ai.operation.name": operation,
|
|
7220
|
+
"gen_ai.system": vendor,
|
|
7221
|
+
"gen_ai.provider.name": vendor
|
|
7222
|
+
};
|
|
7223
|
+
};
|
|
7224
|
+
const markError = (span, error) => {
|
|
7225
|
+
span.setAttribute("error.type", error?.constructor?.name ?? "Error");
|
|
7226
|
+
span.recordException(error);
|
|
7227
|
+
span.setStatus({
|
|
7228
|
+
code: _opentelemetry_api.SpanStatusCode.ERROR,
|
|
7229
|
+
message: error?.message ?? String(error)
|
|
7230
|
+
});
|
|
7231
|
+
};
|
|
7232
|
+
const parseJsonObject = (input) => {
|
|
7233
|
+
if (typeof input !== "string") return input;
|
|
7234
|
+
try {
|
|
7235
|
+
const parsed = JSON.parse(input);
|
|
7236
|
+
return parsed !== null && typeof parsed === "object" ? parsed : input;
|
|
7237
|
+
} catch {
|
|
7238
|
+
return input;
|
|
7239
|
+
}
|
|
7240
|
+
};
|
|
7241
|
+
//#endregion
|
|
7242
|
+
//#region src/opentelemetry-lib/instrumentation/langchain/index.ts
|
|
7243
|
+
const logger$17 = require_utils.initializeLogger();
|
|
7244
|
+
const PATCH_DATA_SYMBOL$1 = Symbol("lmnr.langchain.patchData");
|
|
7245
|
+
const hasOwnPatchData$1 = (target) => Object.getOwnPropertyDescriptor(target, PATCH_DATA_SYMBOL$1) !== void 0;
|
|
7246
|
+
/**
|
|
7247
|
+
* Model classes whose provider SDK Laminar instruments itself (`_llmType()`).
|
|
7248
|
+
* Their LLM calls are handed off: the provider span is the LLM span, with the
|
|
7249
|
+
* provider-specific attributes, and LangChain opens none of its own.
|
|
7250
|
+
*/
|
|
7251
|
+
const HANDOFF_LLM_TYPES = /* @__PURE__ */ new Set([
|
|
7252
|
+
"openai",
|
|
7253
|
+
"azure_openai",
|
|
7254
|
+
"anthropic"
|
|
7255
|
+
]);
|
|
7256
|
+
/**
|
|
7257
|
+
* The single handler injected into every LangChain `CallbackManager`. All its
|
|
7258
|
+
* state is keyed by LangChain run id, so it is shared by every instrumentation
|
|
7259
|
+
* instance (auto and manual) and patched module copy.
|
|
7260
|
+
*/
|
|
7261
|
+
const handler = new LaminarCallbackHandler(true);
|
|
7262
|
+
const topologyStorage = new node_async_hooks.AsyncLocalStorage();
|
|
7263
|
+
handler.takeTopology = () => {
|
|
7264
|
+
const holder = topologyStorage.getStore();
|
|
7265
|
+
const topology = holder?.topology;
|
|
7266
|
+
if (holder) holder.topology = void 0;
|
|
7267
|
+
return topology;
|
|
7268
|
+
};
|
|
7269
|
+
/**
|
|
7270
|
+
* Run `fn` with `ctx` current in both the OTel context (read by OTel-aware
|
|
7271
|
+
* code) and Laminar's context stack (read by `Laminar.startSpan` and
|
|
7272
|
+
* Laminar's own provider instrumentations).
|
|
7273
|
+
*/
|
|
7274
|
+
const runUnder = (ctx, fn) => _opentelemetry_api.context.with(ctx, () => LaminarContextManager.runWithIsolatedContext([...LaminarContextManager.getContextStack(), ctx], fn));
|
|
7275
|
+
/**
|
|
7276
|
+
* Wrap an async iterator so each step runs through `run`.
|
|
7277
|
+
* `AsyncLocalStorage.run` and `context.with` only cover the synchronous part
|
|
7278
|
+
* of the call, so every `next` / `return` / `throw` needs its own.
|
|
7279
|
+
*/
|
|
7280
|
+
const wrapIterator = (iterator, run) => ({
|
|
7281
|
+
next: (...args) => run(() => iterator.next(...args)),
|
|
7282
|
+
return: (value) => run(() => typeof iterator.return === "function" ? iterator.return(value) : Promise.resolve({
|
|
7283
|
+
done: true,
|
|
7284
|
+
value
|
|
7285
|
+
})),
|
|
7286
|
+
throw: (error) => run(() => typeof iterator.throw === "function" ? iterator.throw(error) : Promise.reject(error)),
|
|
7287
|
+
[Symbol.asyncIterator]() {
|
|
7288
|
+
return this;
|
|
7289
|
+
}
|
|
7290
|
+
});
|
|
7291
|
+
/**
|
|
7292
|
+
* Replace the own method `target[method]` with `wrap(original)`. Already
|
|
7293
|
+
* patched methods are left alone, so repeated initialization never
|
|
7294
|
+
* double-wraps.
|
|
7295
|
+
*/
|
|
7296
|
+
const patchMethod = (target, method, wrap) => {
|
|
7297
|
+
if (!target || !Object.getOwnPropertyDescriptor(target, method) || typeof target[method] !== "function") return;
|
|
7298
|
+
if (!hasOwnPatchData$1(target)) Object.defineProperty(target, PATCH_DATA_SYMBOL$1, {
|
|
7299
|
+
value: {},
|
|
7300
|
+
enumerable: false,
|
|
7301
|
+
writable: true,
|
|
7302
|
+
configurable: true
|
|
7303
|
+
});
|
|
7304
|
+
const patchData = target[PATCH_DATA_SYMBOL$1];
|
|
7305
|
+
if (patchData[method]) return;
|
|
7306
|
+
const original = target[method];
|
|
7307
|
+
patchData[method] = original;
|
|
7308
|
+
target[method] = wrap(original);
|
|
7309
|
+
};
|
|
7310
|
+
const unpatchMethod = (target, method) => {
|
|
7311
|
+
if (!target || !hasOwnPatchData$1(target)) return;
|
|
7312
|
+
const patchData = target[PATCH_DATA_SYMBOL$1];
|
|
7313
|
+
const original = patchData[method];
|
|
7314
|
+
if (!original) return;
|
|
7315
|
+
target[method] = original;
|
|
7316
|
+
delete patchData[method];
|
|
7317
|
+
if (Object.keys(patchData).length === 0) delete target[PATCH_DATA_SYMBOL$1];
|
|
7318
|
+
};
|
|
7319
|
+
/**
|
|
7320
|
+
* Inject the handler into every `CallbackManager` LangChain configures.
|
|
7321
|
+
* `configure` delegates to the static `_configureSync`, and LangGraph calls
|
|
7322
|
+
* `_configureSync` directly, so this one method covers both.
|
|
7323
|
+
*/
|
|
7324
|
+
const wrapConfigureSync = (original) => function(inheritableHandlers, ...rest) {
|
|
7325
|
+
const manager = original.call(this, inheritableHandlers, ...rest);
|
|
7326
|
+
if (!manager) return original.call(this, [handler], ...rest);
|
|
7327
|
+
try {
|
|
7328
|
+
if (!manager.handlers?.some((h) => h?.name === "laminar_callback_handler") && typeof manager.addHandler === "function") manager.addHandler(handler, true);
|
|
7329
|
+
} catch (error) {
|
|
7330
|
+
logger$17.debug(`Failed to add the Laminar LangChain handler: ${error}`);
|
|
7331
|
+
}
|
|
7332
|
+
return manager;
|
|
7333
|
+
};
|
|
7334
|
+
/**
|
|
7335
|
+
* Run user code that LangChain runs for a run (a lambda, a tool, a graph
|
|
7336
|
+
* node) under that run's span. LangChain passes it the run's child config,
|
|
7337
|
+
* whose callback manager's parent run id is that run.
|
|
7338
|
+
*/
|
|
7339
|
+
const wrapRunWithConfig = (original) => function(config, ...rest) {
|
|
7340
|
+
let ctx;
|
|
7341
|
+
try {
|
|
7342
|
+
ctx = handler.contextFor(config?.callbacks?.getParentRunId?.());
|
|
7343
|
+
} catch {
|
|
7344
|
+
ctx = void 0;
|
|
7345
|
+
}
|
|
7346
|
+
if (!ctx) return original.call(this, config, ...rest);
|
|
7347
|
+
return runUnder(ctx, () => original.call(this, config, ...rest));
|
|
7348
|
+
};
|
|
7349
|
+
/**
|
|
7350
|
+
* The context an LLM call runs under, or undefined to run it untouched (it is
|
|
7351
|
+
* nested in another LLM call, or tracing is suppressed).
|
|
7352
|
+
*
|
|
7353
|
+
* The call is handed off to Laminar's provider instrumentation when the model
|
|
7354
|
+
* wraps a provider SDK it instruments. Otherwise the handler records the LLM
|
|
7355
|
+
* span and provider instrumentations underneath are suppressed, so a call is
|
|
7356
|
+
* never recorded twice.
|
|
7357
|
+
*/
|
|
7358
|
+
const llmCallContext = (model, callbacks, startedRunManagers) => {
|
|
7359
|
+
const active = _opentelemetry_api.context.active();
|
|
7360
|
+
if (active.getValue(LLM_CALL_KEY) || (0, _opentelemetry_core.isTracingSuppressed)(active)) return;
|
|
7361
|
+
let parentRunId;
|
|
7362
|
+
let llmType;
|
|
7363
|
+
try {
|
|
7364
|
+
parentRunId = callbacks?.getParentRunId?.();
|
|
7365
|
+
llmType = model?._llmType?.();
|
|
7366
|
+
} catch {}
|
|
7367
|
+
const base = handler.contextFor(parentRunId) ?? LaminarContextManager.getContext();
|
|
7368
|
+
const mode = llmType && HANDOFF_LLM_TYPES.has(llmType) && !startedRunManagers ? "handoff" : "own";
|
|
7369
|
+
const call = {
|
|
7370
|
+
mode,
|
|
7371
|
+
recorded: false
|
|
7372
|
+
};
|
|
7373
|
+
const ctx = base.setValue(LLM_CALL_KEY, call);
|
|
7374
|
+
return mode === "own" ? (0, _opentelemetry_core.suppressTracing)(ctx) : ctx;
|
|
7375
|
+
};
|
|
7376
|
+
const wrapGenerateUncached = (original) => function(input, parsedOptions, handledOptions, startedRunManagers, ...rest) {
|
|
7377
|
+
const call = () => original.call(this, input, parsedOptions, handledOptions, startedRunManagers, ...rest);
|
|
7378
|
+
const ctx = llmCallContext(this, handledOptions?.callbacks, startedRunManagers);
|
|
7379
|
+
return ctx ? runUnder(ctx, call) : call();
|
|
7380
|
+
};
|
|
7381
|
+
const wrapModelStreamIterator = (original) => function(input, options, ...rest) {
|
|
7382
|
+
const ctx = llmCallContext(this, options?.callbacks);
|
|
7383
|
+
if (!ctx) return original.call(this, input, options, ...rest);
|
|
7384
|
+
const iterator = runUnder(ctx, () => original.call(this, input, options, ...rest));
|
|
7385
|
+
return wrapIterator(iterator, (fn) => runUnder(ctx, fn));
|
|
7386
|
+
};
|
|
7387
|
+
/**
|
|
7388
|
+
* The graph topology, recorded on the graph's root span the way the Python
|
|
7389
|
+
* SDK does. Only the synchronous `getGraph` is used: it runs before the
|
|
7390
|
+
* graph does, and an async drawing would hold the run back.
|
|
7391
|
+
*/
|
|
7392
|
+
const topologyCache = /* @__PURE__ */ new WeakMap();
|
|
7393
|
+
const graphTopology = (pregel, config) => {
|
|
7394
|
+
const cached = topologyCache.get(pregel);
|
|
7395
|
+
if (cached) return cached;
|
|
7396
|
+
if (typeof pregel?.getGraph !== "function") return void 0;
|
|
7397
|
+
const graph = pregel.getGraph(config);
|
|
7398
|
+
if (!graph || graph instanceof Promise) return void 0;
|
|
7399
|
+
const nodes = Object.values(graph.nodes ?? {}).map((node) => ({
|
|
7400
|
+
id: node.id,
|
|
7401
|
+
name: node.name,
|
|
7402
|
+
metadata: node.metadata ?? null
|
|
7403
|
+
}));
|
|
7404
|
+
const edges = (graph.edges ?? []).map((edge) => ({
|
|
7405
|
+
source: edge.source,
|
|
7406
|
+
target: edge.target,
|
|
7407
|
+
conditional: Boolean(edge.conditional)
|
|
7408
|
+
}));
|
|
7409
|
+
const topology = {
|
|
7410
|
+
"langgraph.nodes": JSON.stringify(nodes),
|
|
7411
|
+
"langgraph.edges": JSON.stringify(edges)
|
|
7412
|
+
};
|
|
7413
|
+
topologyCache.set(pregel, topology);
|
|
7414
|
+
return topology;
|
|
7415
|
+
};
|
|
7416
|
+
/**
|
|
7417
|
+
* Publish the graph topology for the graph's own run, which the handler
|
|
7418
|
+
* starts in the iterator's first step. Each iterator gets its own holder, so
|
|
7419
|
+
* concurrent graph runs never read each other's topology.
|
|
7420
|
+
*/
|
|
7421
|
+
const wrapPregelStreamIterator = (original) => function(input, options, ...rest) {
|
|
7422
|
+
let topology;
|
|
7423
|
+
try {
|
|
7424
|
+
topology = graphTopology(this, options);
|
|
7425
|
+
} catch (error) {
|
|
7426
|
+
logger$17.debug(`Failed to read the LangGraph topology: ${error}`);
|
|
7427
|
+
}
|
|
7428
|
+
const iterator = original.call(this, input, options, ...rest);
|
|
7429
|
+
if (!topology) return iterator;
|
|
7430
|
+
const holder = { topology };
|
|
7431
|
+
return wrapIterator(iterator, (fn) => topologyStorage.run(holder, fn));
|
|
7432
|
+
};
|
|
7433
|
+
/**
|
|
7434
|
+
* `Pregel.prototype` from `@langchain/langgraph/pregel`, or the first
|
|
7435
|
+
* prototype that owns `_streamIterator` above a compiled graph class.
|
|
7436
|
+
*/
|
|
7437
|
+
const pregelPrototype = (module) => {
|
|
7438
|
+
if (typeof module?.Pregel === "function") return module.Pregel.prototype;
|
|
7439
|
+
const graphClass = module?.CompiledStateGraph ?? module?.CompiledGraph ?? module;
|
|
7440
|
+
let proto = typeof graphClass === "function" ? graphClass.prototype : null;
|
|
7441
|
+
while (proto && proto !== Object.prototype) {
|
|
7442
|
+
if (Object.getOwnPropertyDescriptor(proto, "_streamIterator")) return proto;
|
|
7443
|
+
proto = Object.getPrototypeOf(proto);
|
|
7444
|
+
}
|
|
7445
|
+
};
|
|
7446
|
+
const singletonPrototype = (module) => {
|
|
7447
|
+
const singleton = module?.AsyncLocalStorageProviderSingleton;
|
|
7448
|
+
return singleton ? Object.getPrototypeOf(singleton) : void 0;
|
|
7449
|
+
};
|
|
7450
|
+
const CORE_FILES = {
|
|
7451
|
+
callbackManager: ["@langchain/core/dist/callbacks/manager"],
|
|
7452
|
+
singletons: ["@langchain/core/dist/singletons/async_local_storage/index", "@langchain/core/dist/singletons/index"],
|
|
7453
|
+
chatModels: ["@langchain/core/dist/language_models/chat_models"],
|
|
7454
|
+
llms: ["@langchain/core/dist/language_models/llms"]
|
|
7455
|
+
};
|
|
7456
|
+
/**
|
|
7457
|
+
* Instruments LangChain (`@langchain/core`) and LangGraph
|
|
7458
|
+
* (`@langchain/langgraph`) through a callback handler injected into every
|
|
7459
|
+
* callback manager, with wrappers that run user code and provider SDK calls
|
|
7460
|
+
* under the right span.
|
|
7461
|
+
*
|
|
7462
|
+
* Calls made through LangChain's OpenAI and Anthropic integrations are left to
|
|
7463
|
+
* Laminar's OpenAI and Anthropic instrumentations, which record them as the
|
|
7464
|
+
* LLM span. Other model calls are recorded by the handler, with provider
|
|
7465
|
+
* instrumentations underneath suppressed.
|
|
7466
|
+
*/
|
|
7467
|
+
var LangChainInstrumentation = class extends _opentelemetry_instrumentation.InstrumentationBase {
|
|
7468
|
+
constructor(config) {
|
|
7469
|
+
super("@lmnr/langchain-instrumentation", require_utils.version, { enabled: true });
|
|
7470
|
+
this.traceContent = config?.traceContent ?? true;
|
|
7471
|
+
}
|
|
7472
|
+
init() {
|
|
7473
|
+
const coreFiles = (names, patch, unpatch) => names.flatMap((name) => [".cjs", ".js"].map((extension) => new _opentelemetry_instrumentation.InstrumentationNodeModuleFile(`${name}${extension}`, [">=0.3.0"], (exports) => {
|
|
7474
|
+
patch.call(this, exports);
|
|
7475
|
+
return exports;
|
|
7476
|
+
}, (exports) => {
|
|
7477
|
+
if (exports) unpatch.call(this, exports);
|
|
7478
|
+
})));
|
|
7479
|
+
return [new _opentelemetry_instrumentation.InstrumentationNodeModuleDefinition("@langchain/core", [">=0.3.0"], void 0, void 0, [
|
|
7480
|
+
...coreFiles(CORE_FILES.callbackManager, this.patchCallbackManager, this.unpatchCallbackManager),
|
|
7481
|
+
...coreFiles(CORE_FILES.singletons, this.patchSingletons, this.unpatchSingletons),
|
|
7482
|
+
...coreFiles(CORE_FILES.chatModels, this.patchChatModels, this.unpatchChatModels),
|
|
7483
|
+
...coreFiles(CORE_FILES.llms, this.patchLlms, this.unpatchLlms)
|
|
7484
|
+
]), new _opentelemetry_instrumentation.InstrumentationNodeModuleDefinition("@langchain/langgraph", [">=0.2.0"], void 0, void 0, [".cjs", ".js"].map((extension) => new _opentelemetry_instrumentation.InstrumentationNodeModuleFile(`@langchain/langgraph/dist/pregel/index${extension}`, [">=0.2.0"], (exports) => {
|
|
7485
|
+
this.patchLanggraph(exports);
|
|
7486
|
+
return exports;
|
|
7487
|
+
}, (exports) => {
|
|
7488
|
+
if (exports) this.unpatchLanggraph(exports);
|
|
7489
|
+
})))];
|
|
7490
|
+
}
|
|
7491
|
+
/**
|
|
7492
|
+
* Pass every module you use; a module left out is not traced. The model
|
|
7493
|
+
* modules are what lets OpenAI and Anthropic calls be recorded once, by the
|
|
7494
|
+
* provider instrumentation, instead of twice.
|
|
7495
|
+
*/
|
|
7496
|
+
manuallyInstrument(modules) {
|
|
7497
|
+
const { callbackManagerModule, singletonsModule, chatModelsModule, llmsModule, langgraphModule } = modules ?? {};
|
|
7498
|
+
if (!callbackManagerModule && !singletonsModule && !chatModelsModule && !llmsModule && !langgraphModule) {
|
|
7499
|
+
_opentelemetry_api.diag.warn("No modules in langchain manual instrumentation input. Pass at least @langchain/core/callbacks/manager as callbackManagerModule.");
|
|
7500
|
+
return;
|
|
7501
|
+
}
|
|
7502
|
+
_opentelemetry_api.diag.debug("Manually instrumenting LangChain");
|
|
7503
|
+
if (callbackManagerModule && !chatModelsModule) _opentelemetry_api.diag.warn("LangChain chatModelsModule is missing from manual instrumentation input. Chat model calls may be recorded twice. Pass @langchain/core/language_models/chat_models as chatModelsModule.");
|
|
7504
|
+
if (callbackManagerModule) this.patchCallbackManager(callbackManagerModule);
|
|
7505
|
+
if (singletonsModule) this.patchSingletons(singletonsModule);
|
|
7506
|
+
if (chatModelsModule) this.patchChatModels(chatModelsModule);
|
|
7507
|
+
if (llmsModule) this.patchLlms(llmsModule);
|
|
7508
|
+
if (langgraphModule) {
|
|
7509
|
+
if (!pregelPrototype(langgraphModule)) _opentelemetry_api.diag.warn("Could not find Pregel in langchain manual instrumentation input. Pass the @langchain/langgraph module as langgraphModule.");
|
|
7510
|
+
else this.patchLanggraph(langgraphModule);
|
|
7511
|
+
}
|
|
7512
|
+
}
|
|
7513
|
+
patchCallbackManager(moduleExports) {
|
|
7514
|
+
_opentelemetry_api.diag.debug("Patching @langchain/core CallbackManager");
|
|
7515
|
+
handler.traceContent = this.traceContent;
|
|
7516
|
+
patchMethod(moduleExports?.CallbackManager, "_configureSync", wrapConfigureSync);
|
|
7517
|
+
}
|
|
7518
|
+
unpatchCallbackManager(moduleExports) {
|
|
7519
|
+
unpatchMethod(moduleExports?.CallbackManager, "_configureSync");
|
|
7520
|
+
}
|
|
7521
|
+
patchSingletons(moduleExports) {
|
|
7522
|
+
_opentelemetry_api.diag.debug("Patching @langchain/core AsyncLocalStorageProvider");
|
|
7523
|
+
patchMethod(singletonPrototype(moduleExports), "runWithConfig", wrapRunWithConfig);
|
|
7524
|
+
}
|
|
7525
|
+
unpatchSingletons(moduleExports) {
|
|
7526
|
+
unpatchMethod(singletonPrototype(moduleExports), "runWithConfig");
|
|
7527
|
+
}
|
|
7528
|
+
patchChatModels(moduleExports) {
|
|
7529
|
+
_opentelemetry_api.diag.debug("Patching @langchain/core BaseChatModel");
|
|
7530
|
+
this.patchModel(moduleExports?.BaseChatModel?.prototype);
|
|
7531
|
+
}
|
|
7532
|
+
unpatchChatModels(moduleExports) {
|
|
7533
|
+
this.unpatchModel(moduleExports?.BaseChatModel?.prototype);
|
|
7534
|
+
}
|
|
7535
|
+
patchLlms(moduleExports) {
|
|
7536
|
+
_opentelemetry_api.diag.debug("Patching @langchain/core BaseLLM");
|
|
7537
|
+
this.patchModel(moduleExports?.BaseLLM?.prototype);
|
|
7538
|
+
}
|
|
7539
|
+
unpatchLlms(moduleExports) {
|
|
7540
|
+
this.unpatchModel(moduleExports?.BaseLLM?.prototype);
|
|
7541
|
+
}
|
|
7542
|
+
patchModel(proto) {
|
|
7543
|
+
patchMethod(proto, "_generateUncached", wrapGenerateUncached);
|
|
7544
|
+
patchMethod(proto, "_streamIterator", wrapModelStreamIterator);
|
|
7545
|
+
}
|
|
7546
|
+
unpatchModel(proto) {
|
|
7547
|
+
unpatchMethod(proto, "_generateUncached");
|
|
7548
|
+
unpatchMethod(proto, "_streamIterator");
|
|
7549
|
+
}
|
|
7550
|
+
patchLanggraph(moduleExports) {
|
|
7551
|
+
_opentelemetry_api.diag.debug("Patching @langchain/langgraph Pregel");
|
|
7552
|
+
patchMethod(pregelPrototype(moduleExports), "_streamIterator", wrapPregelStreamIterator);
|
|
7553
|
+
}
|
|
7554
|
+
unpatchLanggraph(moduleExports) {
|
|
7555
|
+
unpatchMethod(pregelPrototype(moduleExports), "_streamIterator");
|
|
7556
|
+
}
|
|
7557
|
+
};
|
|
6492
7558
|
const DISABLE_OPENAI_RESPONSES_INSTRUMENTATION_CONTEXT_KEY = (0, _opentelemetry_api.createContextKey)("LMNR_DISABLE_OPENAI_RESPONSES_INSTRUMENTATION");
|
|
6493
7559
|
const systemInstructionsStorage = new async_hooks.AsyncLocalStorage();
|
|
6494
7560
|
const getCurrentSystemInstructions = () => systemInstructionsStorage.getStore();
|
|
@@ -8585,6 +9651,107 @@ var LaminarSpanExporter = class {
|
|
|
8585
9651
|
return this.exporter.forceFlush?.();
|
|
8586
9652
|
}
|
|
8587
9653
|
};
|
|
9654
|
+
const RELEASE_ENV_VARS = [
|
|
9655
|
+
"GITHUB_SHA",
|
|
9656
|
+
"SENTRY_RELEASE",
|
|
9657
|
+
"VERCEL_GIT_COMMIT_SHA",
|
|
9658
|
+
"RENDER_GIT_COMMIT",
|
|
9659
|
+
"RAILWAY_GIT_COMMIT_SHA",
|
|
9660
|
+
"HEROKU_BUILD_COMMIT",
|
|
9661
|
+
"SOURCE_VERSION",
|
|
9662
|
+
"CODEBUILD_RESOLVED_SOURCE_VERSION",
|
|
9663
|
+
"CIRCLE_SHA1",
|
|
9664
|
+
"K_REVISION",
|
|
9665
|
+
"GAE_DEPLOYMENT_ID",
|
|
9666
|
+
"FLY_IMAGE_REF"
|
|
9667
|
+
];
|
|
9668
|
+
/**
|
|
9669
|
+
* The first available of: `explicit`, `LMNR_RELEASE`, a known platform
|
|
9670
|
+
* variable, a numeric AWS Lambda version, the checked-out git commit.
|
|
9671
|
+
*/
|
|
9672
|
+
const detectRelease = (explicit) => {
|
|
9673
|
+
const candidates = [
|
|
9674
|
+
() => explicit,
|
|
9675
|
+
() => env("LMNR_RELEASE"),
|
|
9676
|
+
...RELEASE_ENV_VARS.map((name) => () => env(name)),
|
|
9677
|
+
lambdaVersion,
|
|
9678
|
+
gitHead
|
|
9679
|
+
];
|
|
9680
|
+
for (const candidate of candidates) {
|
|
9681
|
+
const release = clean(candidate());
|
|
9682
|
+
if (release) return release;
|
|
9683
|
+
}
|
|
9684
|
+
};
|
|
9685
|
+
const env = (name) => {
|
|
9686
|
+
try {
|
|
9687
|
+
return process.env[name];
|
|
9688
|
+
} catch {
|
|
9689
|
+
return;
|
|
9690
|
+
}
|
|
9691
|
+
};
|
|
9692
|
+
const clean = (value) => {
|
|
9693
|
+
const trimmed = value?.trim();
|
|
9694
|
+
if (!trimmed) return;
|
|
9695
|
+
const chars = Array.from(trimmed);
|
|
9696
|
+
return chars.length > 128 ? chars.slice(0, 128).join("") : trimmed;
|
|
9697
|
+
};
|
|
9698
|
+
const lambdaVersion = () => {
|
|
9699
|
+
const version = env("AWS_LAMBDA_FUNCTION_VERSION");
|
|
9700
|
+
const fn = env("AWS_LAMBDA_FUNCTION_NAME");
|
|
9701
|
+
if (!version || !/^\d+$/.test(version) || !fn) return;
|
|
9702
|
+
return `${fn}:${version}`;
|
|
9703
|
+
};
|
|
9704
|
+
const isFile = (path) => {
|
|
9705
|
+
try {
|
|
9706
|
+
return (0, node_fs.statSync)(path).isFile();
|
|
9707
|
+
} catch {
|
|
9708
|
+
return false;
|
|
9709
|
+
}
|
|
9710
|
+
};
|
|
9711
|
+
const isDirectory = (path) => {
|
|
9712
|
+
try {
|
|
9713
|
+
return (0, node_fs.statSync)(path).isDirectory();
|
|
9714
|
+
} catch {
|
|
9715
|
+
return false;
|
|
9716
|
+
}
|
|
9717
|
+
};
|
|
9718
|
+
/** The commit `.git/HEAD` points at, read from disk without running git. */
|
|
9719
|
+
const gitHead = () => {
|
|
9720
|
+
try {
|
|
9721
|
+
const gitDir = findGitDir(process.cwd());
|
|
9722
|
+
if (gitDir === void 0) return;
|
|
9723
|
+
const head = (0, node_fs.readFileSync)((0, node_path.join)(gitDir, "HEAD"), "utf8").trim();
|
|
9724
|
+
if (!head.startsWith("ref:")) return head;
|
|
9725
|
+
const ref = head.slice(4).trim();
|
|
9726
|
+
const commonFile = (0, node_path.join)(gitDir, "commondir");
|
|
9727
|
+
const commonDir = isFile(commonFile) ? (0, node_path.resolve)(gitDir, (0, node_fs.readFileSync)(commonFile, "utf8").trim()) : gitDir;
|
|
9728
|
+
for (const refsDir of /* @__PURE__ */ new Set([gitDir, commonDir])) {
|
|
9729
|
+
const refFile = (0, node_path.join)(refsDir, ref);
|
|
9730
|
+
if (isFile(refFile)) return (0, node_fs.readFileSync)(refFile, "utf8").trim();
|
|
9731
|
+
}
|
|
9732
|
+
const packedRefs = (0, node_path.join)(commonDir, "packed-refs");
|
|
9733
|
+
if (isFile(packedRefs)) for (const line of (0, node_fs.readFileSync)(packedRefs, "utf8").split("\n")) {
|
|
9734
|
+
const space = line.indexOf(" ");
|
|
9735
|
+
if (space !== -1 && line.slice(space + 1).trim() === ref) return line.slice(0, space);
|
|
9736
|
+
}
|
|
9737
|
+
} catch {
|
|
9738
|
+
return;
|
|
9739
|
+
}
|
|
9740
|
+
};
|
|
9741
|
+
const findGitDir = (start) => {
|
|
9742
|
+
let directory = (0, node_path.resolve)(start);
|
|
9743
|
+
for (;;) {
|
|
9744
|
+
const dotGit = (0, node_path.join)(directory, ".git");
|
|
9745
|
+
if (isDirectory(dotGit)) return dotGit;
|
|
9746
|
+
if (isFile(dotGit)) {
|
|
9747
|
+
const content = (0, node_fs.readFileSync)(dotGit, "utf8").trim();
|
|
9748
|
+
if (content.startsWith("gitdir:")) return (0, node_path.resolve)(directory, content.slice(7).trim());
|
|
9749
|
+
}
|
|
9750
|
+
const parent = (0, node_path.dirname)(directory);
|
|
9751
|
+
if (parent === directory) return;
|
|
9752
|
+
directory = parent;
|
|
9753
|
+
}
|
|
9754
|
+
};
|
|
8588
9755
|
//#endregion
|
|
8589
9756
|
//#region src/opentelemetry-lib/tracing/processor.ts
|
|
8590
9757
|
var LaminarSpanProcessor = class LaminarSpanProcessor {
|
|
@@ -8602,11 +9769,15 @@ var LaminarSpanProcessor = class LaminarSpanProcessor {
|
|
|
8602
9769
|
* @param {boolean} options.forceHttp - Whether to force HTTP and use OpenTelemetry
|
|
8603
9770
|
* HTTP/protobuf exporter.
|
|
8604
9771
|
* Not recommended with Laminar backends.
|
|
9772
|
+
* @param {string} options.release - The release of the running code, usually
|
|
9773
|
+
* its git commit SHA. Detected from the environment if not provided.
|
|
8605
9774
|
*/
|
|
8606
9775
|
constructor(options = {}) {
|
|
8607
9776
|
this._spanIdToPath = /* @__PURE__ */ new Map();
|
|
8608
9777
|
this._spanIdLists = /* @__PURE__ */ new Map();
|
|
8609
9778
|
this.logger = require_utils.initializeLogger();
|
|
9779
|
+
const wrapped = options.spanProcessor instanceof LaminarSpanProcessor ? options.spanProcessor.release : void 0;
|
|
9780
|
+
this.release = detectRelease(options.release ?? wrapped);
|
|
8610
9781
|
if (options.spanProcessor && options.spanProcessor instanceof LaminarSpanProcessor) {
|
|
8611
9782
|
this.instance = options.spanProcessor.instance;
|
|
8612
9783
|
this._spanIdToPath = options.spanProcessor._spanIdToPath;
|
|
@@ -8652,6 +9823,7 @@ var LaminarSpanProcessor = class LaminarSpanProcessor {
|
|
|
8652
9823
|
span.setAttribute(require_utils.SPAN_SDK_VERSION, require_utils.version);
|
|
8653
9824
|
const langVersion = getLangVersion();
|
|
8654
9825
|
if (langVersion) span.setAttribute(require_utils.SPAN_LANGUAGE_VERSION, langVersion);
|
|
9826
|
+
if (this.release) span.setAttribute(require_utils.SPAN_RELEASE, this.release);
|
|
8655
9827
|
const globalMetadata = LaminarContextManager.getGlobalMetadata();
|
|
8656
9828
|
if (globalMetadata && Object.keys(globalMetadata).length > 0) span.setAttributes(require_utils.metadataToAttributes(globalMetadata));
|
|
8657
9829
|
const associationProperties = _opentelemetry_api.context.active().getValue(ASSOCIATION_PROPERTIES_KEY);
|
|
@@ -9464,7 +10636,7 @@ const initInstrumentations = (client, suppressContentTracing, sessionRecordingOp
|
|
|
9464
10636
|
instrumentations.push(new CohereInstrumentation({ traceContent: !suppressContentTracing }));
|
|
9465
10637
|
instrumentations.push(new _traceloop_instrumentation_bedrock.BedrockInstrumentation({ traceContent: !suppressContentTracing }));
|
|
9466
10638
|
instrumentations.push(new _traceloop_instrumentation_pinecone.PineconeInstrumentation());
|
|
9467
|
-
instrumentations.push(new
|
|
10639
|
+
instrumentations.push(new LangChainInstrumentation({ traceContent: !suppressContentTracing }));
|
|
9468
10640
|
instrumentations.push(new _traceloop_instrumentation_together.TogetherInstrumentation({ traceContent: !suppressContentTracing }));
|
|
9469
10641
|
instrumentations.push(new _traceloop_instrumentation_chromadb.ChromaDBInstrumentation({ traceContent: !suppressContentTracing }));
|
|
9470
10642
|
instrumentations.push(new _traceloop_instrumentation_qdrant.QdrantInstrumentation({ traceContent: !suppressContentTracing }));
|
|
@@ -9520,7 +10692,7 @@ const manuallyInitInstrumentations = (client, instrumentModules, suppressContent
|
|
|
9520
10692
|
instrumentation.manuallyInstrument(instrumentModules.pinecone);
|
|
9521
10693
|
}
|
|
9522
10694
|
if (instrumentModules?.langchain) {
|
|
9523
|
-
const langchainInstrumentation = new
|
|
10695
|
+
const langchainInstrumentation = new LangChainInstrumentation({ traceContent: !suppressContentTracing });
|
|
9524
10696
|
instrumentations.push(langchainInstrumentation);
|
|
9525
10697
|
langchainInstrumentation.manuallyInstrument(instrumentModules.langchain);
|
|
9526
10698
|
}
|
|
@@ -9684,7 +10856,8 @@ const startTracing = (options) => {
|
|
|
9684
10856
|
maxExportBatchSizeBytes: options.maxExportBatchSizeBytes,
|
|
9685
10857
|
flushBySize: options.flushBySize,
|
|
9686
10858
|
exporter: options.exporter,
|
|
9687
|
-
disableBatch: options.disableBatch
|
|
10859
|
+
disableBatch: options.disableBatch,
|
|
10860
|
+
release: options.release
|
|
9688
10861
|
});
|
|
9689
10862
|
const newProvider = new _opentelemetry_sdk_trace_node.NodeTracerProvider({
|
|
9690
10863
|
spanProcessors: [spanProcessor],
|