@lmnr-ai/lmnr 0.8.20 → 0.8.21
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/worker/build.cjs +1 -1
- package/dist/cli/worker/build.mjs +1 -1
- package/dist/cli/worker/index.cjs +1 -1
- package/dist/cli/worker/index.mjs +1 -1
- package/dist/cli.cjs +3 -3
- package/dist/cli.d.cts +1 -1
- package/dist/cli.d.mts +1 -1
- package/dist/cli.mjs +3 -3
- package/dist/{decorators-Cf0xs-v_.mjs → decorators-BDFgXfgI.mjs} +820 -139
- package/dist/decorators-BDFgXfgI.mjs.map +1 -0
- package/dist/{decorators-u7xFb_9W.cjs → decorators-CaTC0lJq.cjs} +831 -138
- package/dist/decorators-CaTC0lJq.cjs.map +1 -0
- package/dist/{dist-BwllJ__m.mjs → dist-B5CmOQ4s.mjs} +3 -3
- package/dist/{dist-BwllJ__m.mjs.map → dist-B5CmOQ4s.mjs.map} +1 -1
- package/dist/{dist-zDtQ_gVq.cjs → dist-B5cKzRzq.cjs} +3 -3
- package/dist/{dist-zDtQ_gVq.cjs.map → dist-B5cKzRzq.cjs.map} +1 -1
- package/dist/{evaluations-D2duRqbG.d.cts → evaluations-BJkIwpmH.d.cts} +15 -1
- package/dist/{evaluations-DEbBIXng.d.mts → evaluations-tqpNgp0P.d.mts} +15 -1
- package/dist/{file-utils-C-auksVC.mjs → file-utils-CHoR9VB8.mjs} +2 -2
- package/dist/{file-utils-C-auksVC.mjs.map → file-utils-CHoR9VB8.mjs.map} +1 -1
- package/dist/file-utils-IBEBwZxq.cjs +2 -0
- package/dist/{file-utils-0mVr0eIv.cjs → file-utils-yJ5ephze.cjs} +2 -2
- package/dist/{file-utils-0mVr0eIv.cjs.map → file-utils-yJ5ephze.cjs.map} +1 -1
- package/dist/index.cjs +563 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +125 -3
- package/dist/index.d.mts +125 -3
- package/dist/index.mjs +564 -11
- package/dist/index.mjs.map +1 -1
- package/dist/{utils-BmWNkeX5.cjs → utils-C8Tl1vKD.cjs} +23 -1
- package/dist/utils-C8Tl1vKD.cjs.map +1 -0
- package/dist/{utils-0WC6BVqs.mjs → utils-CHJ0KZUR.mjs} +12 -2
- package/dist/utils-CHJ0KZUR.mjs.map +1 -0
- package/package.json +4 -3
- package/dist/decorators-Cf0xs-v_.mjs.map +0 -1
- package/dist/decorators-u7xFb_9W.cjs.map +0 -1
- package/dist/file-utils-2hY2DP65.cjs +0 -2
- package/dist/utils-0WC6BVqs.mjs.map +0 -1
- package/dist/utils-BmWNkeX5.cjs.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { r as __require } from "./chunk-BEJ448es.mjs";
|
|
2
|
-
import { n as version, t as LaminarClient } from "./dist-
|
|
3
|
-
import { A as
|
|
2
|
+
import { n as version, t as LaminarClient } from "./dist-B5CmOQ4s.mjs";
|
|
3
|
+
import { A as SPAN_OUTPUT, C as PARENT_SPAN_PATH, D as SPAN_INPUT, E as SPAN_IDS_PATH, F as TRACE_TYPE, I as USER_ID, M as SPAN_SDK_VERSION, N as SPAN_TYPE, O as SPAN_INSTRUMENTATION_SOURCE, P as TRACE_HAS_BROWSER_SESSION, S as PARENT_SPAN_IDS_PATH, T as SESSION_ID, _ as validateTracingConfig, c as loadEnv, g as tryToOtelSpanContext, h as parseOtelHeaders, j as SPAN_PATH, k as SPAN_LANGUAGE_VERSION, l as metadataToAttributes, m as otelTraceIdToUUID, o as getOtelEnvVar, p as otelSpanIdToUUID, r as deserializeLaminarSpanContext, s as initializeLogger, t as NIL_UUID, u as newUUID, v as ASSOCIATION_PROPERTIES, w as ROLLOUT_SESSION_ID, x as LaminarAttributes, y as ASSOCIATION_PROPERTIES_OVERRIDES } from "./utils-CHJ0KZUR.mjs";
|
|
4
4
|
import { DiagConsoleLogger, DiagLogLevel, ROOT_CONTEXT, SpanStatusCode, context, createContextKey, diag, isSpanContextValid, trace } from "@opentelemetry/api";
|
|
5
5
|
import { AsyncLocalStorageContextManager } from "@opentelemetry/context-async-hooks";
|
|
6
6
|
import { InstrumentationBase, InstrumentationNodeModuleDefinition, registerInstrumentations } from "@opentelemetry/instrumentation";
|
|
@@ -29,7 +29,7 @@ import { Metadata } from "@grpc/grpc-js";
|
|
|
29
29
|
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-grpc";
|
|
30
30
|
import { OTLPTraceExporter as OTLPTraceExporter$1 } from "@opentelemetry/exporter-trace-otlp-proto";
|
|
31
31
|
//#region src/opentelemetry-lib/tracing/compat.ts
|
|
32
|
-
const logger$
|
|
32
|
+
const logger$17 = initializeLogger();
|
|
33
33
|
const makeSpanOtelV2Compatible = (span) => {
|
|
34
34
|
const spanAny = span;
|
|
35
35
|
if (spanAny.instrumentationScope && !spanAny.instrumentationLibrary) Object.assign(span, { instrumentationLibrary: spanAny.instrumentationScope });
|
|
@@ -75,7 +75,7 @@ const createResource = (attributes) => {
|
|
|
75
75
|
if (resources.Resource) return new resources.Resource(attributes);
|
|
76
76
|
throw new Error("Unable to create Resource: neither v1 nor v2 API found");
|
|
77
77
|
} catch {
|
|
78
|
-
logger$
|
|
78
|
+
logger$17.debug("Laminar failed to @opentelemetry/resources, continuing without it");
|
|
79
79
|
return;
|
|
80
80
|
}
|
|
81
81
|
};
|
|
@@ -257,7 +257,7 @@ const consumeResponse = async (response) => {
|
|
|
257
257
|
};
|
|
258
258
|
//#endregion
|
|
259
259
|
//#region src/opentelemetry-lib/tracing/stream-utils.ts
|
|
260
|
-
const logger$
|
|
260
|
+
const logger$16 = initializeLogger();
|
|
261
261
|
const pendingStreamProcessing = /* @__PURE__ */ new Set();
|
|
262
262
|
/**
|
|
263
263
|
* Wait for all pending stream processing to complete with a timeout
|
|
@@ -265,7 +265,7 @@ const pendingStreamProcessing = /* @__PURE__ */ new Set();
|
|
|
265
265
|
*/
|
|
266
266
|
const waitForPendingStreams = async (timeoutMs = 5e3) => {
|
|
267
267
|
if (pendingStreamProcessing.size === 0) return;
|
|
268
|
-
logger$
|
|
268
|
+
logger$16.debug(`Waiting for ${pendingStreamProcessing.size} pending stream(s)`);
|
|
269
269
|
const initialCount = pendingStreamProcessing.size;
|
|
270
270
|
const pendingPromises = Array.from(pendingStreamProcessing);
|
|
271
271
|
let timedOut = false;
|
|
@@ -276,7 +276,7 @@ const waitForPendingStreams = async (timeoutMs = 5e3) => {
|
|
|
276
276
|
}, timeoutMs);
|
|
277
277
|
});
|
|
278
278
|
await Promise.race([Promise.allSettled(pendingPromises), timeoutPromise]);
|
|
279
|
-
if (timedOut && pendingStreamProcessing.size > 0) logger$
|
|
279
|
+
if (timedOut && pendingStreamProcessing.size > 0) logger$16.warn(`Timeout waiting for ${pendingStreamProcessing.size} pending stream(s) after ${timeoutMs}ms (started with ${initialCount})`);
|
|
280
280
|
};
|
|
281
281
|
/**
|
|
282
282
|
* Consumes a stream result to ensure background processing completes.
|
|
@@ -287,15 +287,15 @@ const waitForPendingStreams = async (timeoutMs = 5e3) => {
|
|
|
287
287
|
const consumeStreamResult = async (result) => {
|
|
288
288
|
const streamInfo = getStream(result);
|
|
289
289
|
if (streamInfo.type === null) {
|
|
290
|
-
logger$
|
|
290
|
+
logger$16.debug("Result is not a stream, returning as-is");
|
|
291
291
|
return result;
|
|
292
292
|
}
|
|
293
|
-
logger$
|
|
293
|
+
logger$16.debug("Result is a stream, consuming...");
|
|
294
294
|
if (streamInfo.type === "aisdk-result") {
|
|
295
295
|
try {
|
|
296
296
|
if ("text" in streamInfo.result) await streamInfo.result.text;
|
|
297
297
|
} catch (error) {
|
|
298
|
-
logger$
|
|
298
|
+
logger$16.warn(`Error consuming AI SDK result stream: ${error instanceof Error ? error.message : String(error)}`);
|
|
299
299
|
}
|
|
300
300
|
return result;
|
|
301
301
|
}
|
|
@@ -313,7 +313,7 @@ const consumeStreamResult = async (result) => {
|
|
|
313
313
|
reader.releaseLock();
|
|
314
314
|
}
|
|
315
315
|
} catch (error) {
|
|
316
|
-
logger$
|
|
316
|
+
logger$16.warn(`Error consuming ReadableStream: ${error instanceof Error ? error.message : String(error)}`);
|
|
317
317
|
}
|
|
318
318
|
return {
|
|
319
319
|
type: "stream",
|
|
@@ -325,7 +325,7 @@ const consumeStreamResult = async (result) => {
|
|
|
325
325
|
try {
|
|
326
326
|
for await (const chunk of streamInfo.iterable) chunks.push(chunk);
|
|
327
327
|
} catch (error) {
|
|
328
|
-
logger$
|
|
328
|
+
logger$16.warn(`Error consuming AsyncIterable: ${error instanceof Error ? error.message : String(error)}`);
|
|
329
329
|
}
|
|
330
330
|
return {
|
|
331
331
|
type: "async-iterable",
|
|
@@ -334,13 +334,13 @@ const consumeStreamResult = async (result) => {
|
|
|
334
334
|
}
|
|
335
335
|
if (streamInfo.type === "response") try {
|
|
336
336
|
const { chunks, error } = await consumeResponse(streamInfo.response);
|
|
337
|
-
if (error) logger$
|
|
337
|
+
if (error) logger$16.warn(`Error consuming Response: ${error instanceof Error ? error.message : String(error)}`);
|
|
338
338
|
return {
|
|
339
339
|
type: "response",
|
|
340
340
|
chunks
|
|
341
341
|
};
|
|
342
342
|
} catch (error) {
|
|
343
|
-
logger$
|
|
343
|
+
logger$16.warn(`Error consuming Response: ${error instanceof Error ? error.message : String(error)}`);
|
|
344
344
|
return result;
|
|
345
345
|
}
|
|
346
346
|
return result;
|
|
@@ -359,34 +359,34 @@ const trackStreamProcessing = (task) => {
|
|
|
359
359
|
* while passing through the original result to the caller
|
|
360
360
|
*/
|
|
361
361
|
const handleStreamResult = (originalResult, streamInfo, span, ignoreOutput, serialize) => {
|
|
362
|
-
logger$
|
|
362
|
+
logger$16.debug(`Handling stream result of type: ${streamInfo.type}`);
|
|
363
363
|
if (streamInfo.type === "aisdk-result") {
|
|
364
364
|
trackStreamProcessing(async () => {
|
|
365
|
-
logger$
|
|
365
|
+
logger$16.debug("Starting background processing for AI SDK result");
|
|
366
366
|
let partialOutput = {};
|
|
367
367
|
try {
|
|
368
368
|
partialOutput = await consumeAISDKResult(streamInfo.result);
|
|
369
369
|
if (shouldSendTraces() && !ignoreOutput) try {
|
|
370
370
|
span.setAttribute(SPAN_OUTPUT, serialize(partialOutput));
|
|
371
371
|
} catch (error) {
|
|
372
|
-
logger$
|
|
372
|
+
logger$16.warn(`Failed to serialize AI SDK stream output: ${error instanceof Error ? error.message : String(error)}`);
|
|
373
373
|
}
|
|
374
374
|
} catch (error) {
|
|
375
375
|
if (Object.keys(partialOutput).length > 0 && shouldSendTraces() && !ignoreOutput) try {
|
|
376
376
|
span.setAttribute(SPAN_OUTPUT, serialize(partialOutput));
|
|
377
377
|
} catch (serError) {
|
|
378
|
-
logger$
|
|
378
|
+
logger$16.warn(`Failed to serialize partial AI SDK output: ${serError instanceof Error ? serError.message : String(serError)}`);
|
|
379
379
|
}
|
|
380
380
|
span.recordException(error);
|
|
381
381
|
} finally {
|
|
382
|
-
logger$
|
|
382
|
+
logger$16.debug("Ending span for AI SDK result");
|
|
383
383
|
span.end();
|
|
384
384
|
}
|
|
385
385
|
});
|
|
386
386
|
return originalResult;
|
|
387
387
|
}
|
|
388
388
|
if (streamInfo.type === "readable-stream") {
|
|
389
|
-
logger$
|
|
389
|
+
logger$16.debug("Setting up background processing for ReadableStream");
|
|
390
390
|
const { stream, dataPromise } = consumeAndTeeReadableStream(streamInfo.stream);
|
|
391
391
|
trackStreamProcessing(async () => {
|
|
392
392
|
try {
|
|
@@ -398,18 +398,18 @@ const handleStreamResult = (originalResult, streamInfo, span, ignoreOutput, seri
|
|
|
398
398
|
};
|
|
399
399
|
span.setAttribute(SPAN_OUTPUT, serialize(output));
|
|
400
400
|
} catch (serError) {
|
|
401
|
-
logger$
|
|
401
|
+
logger$16.warn(`Failed to serialize stream output: ${serError instanceof Error ? serError.message : String(serError)}`);
|
|
402
402
|
}
|
|
403
403
|
if (error) span.recordException(error);
|
|
404
404
|
} finally {
|
|
405
|
-
logger$
|
|
405
|
+
logger$16.debug("Ending span for ReadableStream");
|
|
406
406
|
span.end();
|
|
407
407
|
}
|
|
408
408
|
});
|
|
409
409
|
return stream;
|
|
410
410
|
}
|
|
411
411
|
if (streamInfo.type === "async-iterable") {
|
|
412
|
-
logger$
|
|
412
|
+
logger$16.debug("Setting up background processing for AsyncIterable");
|
|
413
413
|
const { iterable, dataPromise } = consumeAndTeeAsyncIterable(streamInfo.iterable);
|
|
414
414
|
trackStreamProcessing(async () => {
|
|
415
415
|
try {
|
|
@@ -421,18 +421,18 @@ const handleStreamResult = (originalResult, streamInfo, span, ignoreOutput, seri
|
|
|
421
421
|
};
|
|
422
422
|
span.setAttribute(SPAN_OUTPUT, serialize(output));
|
|
423
423
|
} catch (serError) {
|
|
424
|
-
logger$
|
|
424
|
+
logger$16.warn(`Failed to serialize async iterable output: ${serError instanceof Error ? serError.message : String(serError)}`);
|
|
425
425
|
}
|
|
426
426
|
if (error) span.recordException(error);
|
|
427
427
|
} finally {
|
|
428
|
-
logger$
|
|
428
|
+
logger$16.debug("Ending span for AsyncIterable");
|
|
429
429
|
span.end();
|
|
430
430
|
}
|
|
431
431
|
});
|
|
432
432
|
return iterable;
|
|
433
433
|
}
|
|
434
434
|
if (streamInfo.type === "response") {
|
|
435
|
-
logger$
|
|
435
|
+
logger$16.debug("Setting up background processing for Response");
|
|
436
436
|
const originalResponse = streamInfo.response;
|
|
437
437
|
if (!originalResponse.body) {
|
|
438
438
|
span.end();
|
|
@@ -454,19 +454,19 @@ const handleStreamResult = (originalResult, streamInfo, span, ignoreOutput, seri
|
|
|
454
454
|
};
|
|
455
455
|
span.setAttribute(SPAN_OUTPUT, serialize(output));
|
|
456
456
|
} catch (serError) {
|
|
457
|
-
logger$
|
|
457
|
+
logger$16.warn(`Failed to serialize response output: ${serError instanceof Error ? serError.message : String(serError)}`);
|
|
458
458
|
}
|
|
459
459
|
if (error) span.recordException(error);
|
|
460
460
|
} catch (err) {
|
|
461
461
|
span.recordException(err);
|
|
462
462
|
} finally {
|
|
463
|
-
logger$
|
|
463
|
+
logger$16.debug("Ending span for Response");
|
|
464
464
|
span.end();
|
|
465
465
|
}
|
|
466
466
|
});
|
|
467
467
|
return newResponse;
|
|
468
468
|
}
|
|
469
|
-
logger$
|
|
469
|
+
logger$16.warn("Stream type not handled, ending span immediately");
|
|
470
470
|
span.end();
|
|
471
471
|
return originalResult;
|
|
472
472
|
};
|
|
@@ -487,7 +487,7 @@ let TracingLevel = /* @__PURE__ */ function(TracingLevel) {
|
|
|
487
487
|
}({});
|
|
488
488
|
//#endregion
|
|
489
489
|
//#region src/opentelemetry-lib/tracing/span.ts
|
|
490
|
-
const logger$
|
|
490
|
+
const logger$15 = initializeLogger();
|
|
491
491
|
var LaminarSpan = class LaminarSpan {
|
|
492
492
|
constructor(span, activated) {
|
|
493
493
|
if (span instanceof LaminarSpan) {
|
|
@@ -550,8 +550,15 @@ var LaminarSpan = class LaminarSpan {
|
|
|
550
550
|
if (!this._span.isRecording()) return this._span.end(endTime);
|
|
551
551
|
LaminarContextManager.removeActiveSpan(this.spanContext().spanId);
|
|
552
552
|
if (this._activated) LaminarContextManager.popContext();
|
|
553
|
+
if (this._globalActiveContext !== void 0) {
|
|
554
|
+
LaminarContextManager.popGlobalContext(this._globalActiveContext);
|
|
555
|
+
this._globalActiveContext = void 0;
|
|
556
|
+
}
|
|
553
557
|
return this._span.end(endTime);
|
|
554
558
|
}
|
|
559
|
+
setGlobalActiveContext(context) {
|
|
560
|
+
this._globalActiveContext = context;
|
|
561
|
+
}
|
|
555
562
|
set activated(activated) {
|
|
556
563
|
this._activated = activated;
|
|
557
564
|
}
|
|
@@ -612,7 +619,7 @@ var LaminarSpan = class LaminarSpan {
|
|
|
612
619
|
} catch {}
|
|
613
620
|
metadata[key.replace(`${ASSOCIATION_PROPERTIES}.metadata.`, "")] = value;
|
|
614
621
|
}
|
|
615
|
-
} else logger$
|
|
622
|
+
} else logger$15.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.");
|
|
616
623
|
return {
|
|
617
624
|
spanId: otelSpanIdToUUID(this._span.spanContext().spanId),
|
|
618
625
|
traceId: otelTraceIdToUUID(this._span.spanContext().traceId),
|
|
@@ -639,14 +646,14 @@ var LaminarSpan = class LaminarSpan {
|
|
|
639
646
|
}
|
|
640
647
|
get tags() {
|
|
641
648
|
if (!this._span.attributes) {
|
|
642
|
-
logger$
|
|
649
|
+
logger$15.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.");
|
|
643
650
|
return [];
|
|
644
651
|
}
|
|
645
652
|
return this._span.attributes[`lmnr.association.properties.tags`] ?? [];
|
|
646
653
|
}
|
|
647
654
|
get laminarAssociationProperties() {
|
|
648
655
|
if (!this._span.attributes) {
|
|
649
|
-
logger$
|
|
656
|
+
logger$15.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.");
|
|
650
657
|
return {};
|
|
651
658
|
}
|
|
652
659
|
try {
|
|
@@ -716,24 +723,32 @@ var LaminarContextManager = class {
|
|
|
716
723
|
static {
|
|
717
724
|
this._activeSpans = /* @__PURE__ */ new Set();
|
|
718
725
|
}
|
|
726
|
+
static {
|
|
727
|
+
this._globalActiveContexts = [];
|
|
728
|
+
}
|
|
719
729
|
constructor() {
|
|
720
730
|
throw new Error("LaminarContextManager is a static class and cannot be instantiated");
|
|
721
731
|
}
|
|
722
|
-
static
|
|
723
|
-
const
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
if (this._activeSpans.has(span.spanContext().spanId)) return context;
|
|
733
|
-
} catch {
|
|
734
|
-
return context;
|
|
735
|
-
}
|
|
732
|
+
static isValidContext(context) {
|
|
733
|
+
const span = trace.getSpan(context);
|
|
734
|
+
if (!span) return true;
|
|
735
|
+
if (!span.isRecording() && span.spanContext().isRemote) return true;
|
|
736
|
+
if (!(span instanceof LaminarSpan)) return true;
|
|
737
|
+
if (!span.isActivated) return true;
|
|
738
|
+
try {
|
|
739
|
+
return this._activeSpans.has(span.spanContext().spanId);
|
|
740
|
+
} catch {
|
|
741
|
+
return true;
|
|
736
742
|
}
|
|
743
|
+
}
|
|
744
|
+
static findLatestValidContext(contexts) {
|
|
745
|
+
for (let i = contexts.length - 1; i >= 0; i--) if (this.isValidContext(contexts[i])) return contexts[i];
|
|
746
|
+
}
|
|
747
|
+
static getContext() {
|
|
748
|
+
const asyncContext = this.findLatestValidContext(this.getContextStack());
|
|
749
|
+
if (asyncContext !== void 0) return asyncContext;
|
|
750
|
+
const globalContext = this.findLatestValidContext(this._globalActiveContexts);
|
|
751
|
+
if (globalContext !== void 0) return globalContext;
|
|
737
752
|
return ROOT_CONTEXT;
|
|
738
753
|
}
|
|
739
754
|
static pushContext(context) {
|
|
@@ -755,8 +770,31 @@ var LaminarContextManager = class {
|
|
|
755
770
|
this._asyncLocalStorage.enterWith(newContexts);
|
|
756
771
|
}
|
|
757
772
|
}
|
|
773
|
+
static pushGlobalContext(context) {
|
|
774
|
+
this._globalActiveContexts.push(context);
|
|
775
|
+
}
|
|
776
|
+
static removeContext(context) {
|
|
777
|
+
const contexts = this.getContextStack();
|
|
778
|
+
if (contexts.length === 0) return;
|
|
779
|
+
for (let i = contexts.length - 1; i >= 0; i--) if (contexts[i] === context) {
|
|
780
|
+
const newContexts = contexts.slice(0, i).concat(contexts.slice(i + 1));
|
|
781
|
+
this._asyncLocalStorage.enterWith(newContexts);
|
|
782
|
+
return;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
static popGlobalContext(context) {
|
|
786
|
+
if (context !== void 0) {
|
|
787
|
+
for (let i = this._globalActiveContexts.length - 1; i >= 0; i--) if (this._globalActiveContexts[i] === context) {
|
|
788
|
+
this._globalActiveContexts.splice(i, 1);
|
|
789
|
+
return;
|
|
790
|
+
}
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
if (this._globalActiveContexts.length > 0) this._globalActiveContexts.pop();
|
|
794
|
+
}
|
|
758
795
|
static clearContexts() {
|
|
759
796
|
this._asyncLocalStorage.enterWith([]);
|
|
797
|
+
this._globalActiveContexts = [];
|
|
760
798
|
}
|
|
761
799
|
static clearActiveSpans() {
|
|
762
800
|
this._activeSpans.clear();
|
|
@@ -814,7 +852,7 @@ var LaminarContextManager = class {
|
|
|
814
852
|
};
|
|
815
853
|
//#endregion
|
|
816
854
|
//#region src/opentelemetry-lib/instrumentation/claude-agent-sdk/proxy.ts
|
|
817
|
-
const logger$
|
|
855
|
+
const logger$14 = initializeLogger();
|
|
818
856
|
const DEFAULT_ANTHROPIC_BASE_URL = "https://api.anthropic.com";
|
|
819
857
|
const DEFAULT_CC_PROXY_PORT = 45667;
|
|
820
858
|
const CC_PROXY_PORT_ATTEMPTS = 50;
|
|
@@ -824,6 +862,8 @@ const FOUNDRY_USE_ENV = "CLAUDE_CODE_USE_FOUNDRY";
|
|
|
824
862
|
const BEDROCK_BASE_URL_ENV = "ANTHROPIC_BEDROCK_BASE_URL";
|
|
825
863
|
const BEDROCK_USE_ENV = "CLAUDE_CODE_USE_BEDROCK";
|
|
826
864
|
const BEDROCK_AWS_REGION_ENV = "AWS_REGION";
|
|
865
|
+
const VERTEX_BASE_URL_ENV = "ANTHROPIC_VERTEX_BASE_URL";
|
|
866
|
+
const VERTEX_USE_ENV = "CLAUDE_CODE_USE_VERTEX";
|
|
827
867
|
const activeProxyServers = /* @__PURE__ */ new Set();
|
|
828
868
|
let globalShutdownRegistered = false;
|
|
829
869
|
/**
|
|
@@ -862,6 +902,9 @@ const getRegionFromAwsConfig = (profile) => {
|
|
|
862
902
|
* - Use ANTHROPIC_BEDROCK_BASE_URL, or
|
|
863
903
|
* - Construct from AWS_REGION env var, or
|
|
864
904
|
* - Construct by reading region from ~/.aws/config via AWS_PROFILE
|
|
905
|
+
* - If CLAUDE_CODE_USE_VERTEX is truthy:
|
|
906
|
+
* - Use ANTHROPIC_VERTEX_BASE_URL, or
|
|
907
|
+
* - Construct from CLOUD_ML_REGION and ANTHROPIC_VERTEX_PROJECT_ID
|
|
865
908
|
* 4. ANTHROPIC_BASE_URL - standard Anthropic API base URL
|
|
866
909
|
* 5. Fall back to default (https://api.anthropic.com)
|
|
867
910
|
*
|
|
@@ -882,7 +925,7 @@ const resolveTargetUrlFromEnv = (envDict, fallback = DEFAULT_ANTHROPIC_BASE_URL)
|
|
|
882
925
|
if (foundryBaseUrl) return foundryBaseUrl.replace(/\/$/, "");
|
|
883
926
|
const foundryResource = getEnvValue(FOUNDRY_RESOURCE_ENV);
|
|
884
927
|
if (foundryResource) return `https://${foundryResource}.services.ai.azure.com/anthropic`;
|
|
885
|
-
logger$
|
|
928
|
+
logger$14.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.`);
|
|
886
929
|
return null;
|
|
887
930
|
}
|
|
888
931
|
if (isTruthyEnv(getEnvValue(BEDROCK_USE_ENV))) {
|
|
@@ -891,9 +934,14 @@ const resolveTargetUrlFromEnv = (envDict, fallback = DEFAULT_ANTHROPIC_BASE_URL)
|
|
|
891
934
|
let region = getEnvValue(BEDROCK_AWS_REGION_ENV);
|
|
892
935
|
if (!region) region = getRegionFromAwsConfig(getEnvValue("AWS_PROFILE") || "default") ?? void 0;
|
|
893
936
|
if (region) return `https://bedrock-runtime.${region}.amazonaws.com`;
|
|
894
|
-
logger$
|
|
937
|
+
logger$14.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.`);
|
|
895
938
|
return null;
|
|
896
939
|
}
|
|
940
|
+
if (isTruthyEnv(getEnvValue(VERTEX_USE_ENV))) {
|
|
941
|
+
const vertexBaseUrl = getEnvValue(VERTEX_BASE_URL_ENV);
|
|
942
|
+
if (vertexBaseUrl) return vertexBaseUrl.replace(/\/$/, "");
|
|
943
|
+
return `https://aiplatform.googleapis.com/v1`;
|
|
944
|
+
}
|
|
897
945
|
const anthropicBaseUrl = getEnvValue("ANTHROPIC_BASE_URL");
|
|
898
946
|
if (anthropicBaseUrl) return anthropicBaseUrl.replace(/\/$/, "");
|
|
899
947
|
return fallback;
|
|
@@ -968,11 +1016,11 @@ const waitForPort = (port, timeoutMs = 5e3) => new Promise((resolve) => {
|
|
|
968
1016
|
const registerGlobalProxyShutdown = () => {
|
|
969
1017
|
if (!globalShutdownRegistered) {
|
|
970
1018
|
process.on("exit", () => {
|
|
971
|
-
logger$
|
|
1019
|
+
logger$14.debug("process.on(\"exit\") called - stopping all active proxies");
|
|
972
1020
|
for (const proxyServer of activeProxyServers) try {
|
|
973
1021
|
proxyServer.stopServer();
|
|
974
1022
|
} catch (e) {
|
|
975
|
-
logger$
|
|
1023
|
+
logger$14.debug(`Failed to stop proxy: ${e instanceof Error ? e.message : String(e)}`);
|
|
976
1024
|
}
|
|
977
1025
|
activeProxyServers.clear();
|
|
978
1026
|
});
|
|
@@ -987,28 +1035,28 @@ const createProxyInstance = async ({ env }) => {
|
|
|
987
1035
|
try {
|
|
988
1036
|
const port = await findAvailablePort(DEFAULT_CC_PROXY_PORT, CC_PROXY_PORT_ATTEMPTS);
|
|
989
1037
|
if (port === null) {
|
|
990
|
-
logger$
|
|
1038
|
+
logger$14.warn("Unable to allocate port for cc-proxy.");
|
|
991
1039
|
return null;
|
|
992
1040
|
}
|
|
993
1041
|
const targetUrl = resolveTargetUrlFromEnv(env);
|
|
994
1042
|
if (!targetUrl) {
|
|
995
|
-
logger$
|
|
1043
|
+
logger$14.warn("Unable to resolve target URL for cc-proxy (provider misconfigured).");
|
|
996
1044
|
return null;
|
|
997
1045
|
}
|
|
998
|
-
logger$
|
|
1046
|
+
logger$14.debug(`Creating proxy instance on port ${port} targeting: ${targetUrl}`);
|
|
999
1047
|
try {
|
|
1000
1048
|
const { ProxyServer } = __require("@lmnr-ai/claude-code-proxy");
|
|
1001
1049
|
const proxyServer = new ProxyServer(port);
|
|
1002
1050
|
proxyServer.runServer(targetUrl);
|
|
1003
1051
|
if (!await waitForPort(port)) {
|
|
1004
|
-
logger$
|
|
1052
|
+
logger$14.warn(`cc-proxy failed to start on port ${port}`);
|
|
1005
1053
|
proxyServer.stopServer();
|
|
1006
1054
|
return null;
|
|
1007
1055
|
}
|
|
1008
1056
|
const proxyBaseUrl = `http://127.0.0.1:${port}`;
|
|
1009
1057
|
activeProxyServers.add(proxyServer);
|
|
1010
1058
|
registerGlobalProxyShutdown();
|
|
1011
|
-
logger$
|
|
1059
|
+
logger$14.info(`Started claude proxy server on: ${proxyBaseUrl}`);
|
|
1012
1060
|
return {
|
|
1013
1061
|
server: proxyServer,
|
|
1014
1062
|
baseUrl: proxyBaseUrl,
|
|
@@ -1016,11 +1064,11 @@ const createProxyInstance = async ({ env }) => {
|
|
|
1016
1064
|
targetUrl
|
|
1017
1065
|
};
|
|
1018
1066
|
} catch (e) {
|
|
1019
|
-
logger$
|
|
1067
|
+
logger$14.warn(`Unable to start cc-proxy: ${e instanceof Error ? e.message : String(e)}`);
|
|
1020
1068
|
return null;
|
|
1021
1069
|
}
|
|
1022
1070
|
} catch (e) {
|
|
1023
|
-
logger$
|
|
1071
|
+
logger$14.warn(`Failed to create proxy instance: ${e instanceof Error ? e.message : String(e)}`);
|
|
1024
1072
|
return null;
|
|
1025
1073
|
}
|
|
1026
1074
|
};
|
|
@@ -1030,11 +1078,11 @@ const createProxyInstance = async ({ env }) => {
|
|
|
1030
1078
|
const stopProxyInstance = (instance) => {
|
|
1031
1079
|
if (!instance) return;
|
|
1032
1080
|
try {
|
|
1033
|
-
logger$
|
|
1081
|
+
logger$14.debug(`Stopping proxy instance on port ${instance.port}`);
|
|
1034
1082
|
instance.server.stopServer();
|
|
1035
1083
|
activeProxyServers.delete(instance.server);
|
|
1036
1084
|
} catch (e) {
|
|
1037
|
-
logger$
|
|
1085
|
+
logger$14.debug(`Failed to stop proxy instance: ${e instanceof Error ? e.message : String(e)}`);
|
|
1038
1086
|
}
|
|
1039
1087
|
};
|
|
1040
1088
|
/**
|
|
@@ -1042,11 +1090,11 @@ const stopProxyInstance = (instance) => {
|
|
|
1042
1090
|
* Used during shutdown to ensure cleanup
|
|
1043
1091
|
*/
|
|
1044
1092
|
const forceReleaseProxy = () => {
|
|
1045
|
-
logger$
|
|
1093
|
+
logger$14.debug(`Force stopping all ${activeProxyServers.size} active proxy servers`);
|
|
1046
1094
|
for (const proxyServer of activeProxyServers) try {
|
|
1047
1095
|
proxyServer.stopServer();
|
|
1048
1096
|
} catch (e) {
|
|
1049
|
-
logger$
|
|
1097
|
+
logger$14.debug(`Failed to stop proxy: ${e instanceof Error ? e.message : String(e)}`);
|
|
1050
1098
|
}
|
|
1051
1099
|
activeProxyServers.clear();
|
|
1052
1100
|
};
|
|
@@ -1096,14 +1144,14 @@ const setTraceToProxyInstance = async (instance) => {
|
|
|
1096
1144
|
spanPath: payload.span_path,
|
|
1097
1145
|
laminarUrl: payload.laminar_url
|
|
1098
1146
|
});
|
|
1099
|
-
logger$
|
|
1147
|
+
logger$14.debug(`Set trace context to proxy on port ${instance.port}`);
|
|
1100
1148
|
} catch (e) {
|
|
1101
|
-
logger$
|
|
1149
|
+
logger$14.debug(`Unable to set trace context to proxy on port ${instance.port}: ` + (e instanceof Error ? e.message : String(e)));
|
|
1102
1150
|
}
|
|
1103
1151
|
};
|
|
1104
1152
|
//#endregion
|
|
1105
1153
|
//#region src/opentelemetry-lib/instrumentation/claude-agent-sdk/index.ts
|
|
1106
|
-
const logger$
|
|
1154
|
+
const logger$13 = initializeLogger();
|
|
1107
1155
|
/**
|
|
1108
1156
|
* Create an instrumented version of the claude-agent-sdk query function.
|
|
1109
1157
|
* This can be used when importing the query function before Laminar initialization.
|
|
@@ -1130,9 +1178,9 @@ function instrumentClaudeAgentQuery(originalQuery) {
|
|
|
1130
1178
|
const targetUrl = resolveTargetUrlFromEnv(mergedEnv);
|
|
1131
1179
|
proxyInstance = await createProxyInstance({ env: mergedEnv });
|
|
1132
1180
|
if (proxyInstance && targetUrl) {
|
|
1133
|
-
logger$
|
|
1181
|
+
logger$13.debug(`Using proxy on port ${proxyInstance.port}`);
|
|
1134
1182
|
await Laminar.withSpan(span, async () => {
|
|
1135
|
-
logger$
|
|
1183
|
+
logger$13.debug("Setting trace to proxy instance...");
|
|
1136
1184
|
await setTraceToProxyInstance(proxyInstance);
|
|
1137
1185
|
});
|
|
1138
1186
|
const varsToRemove = getEnvVarsToRemove(mergedEnv);
|
|
@@ -1144,7 +1192,8 @@ function instrumentClaudeAgentQuery(originalQuery) {
|
|
|
1144
1192
|
for (const varName of varsToRemove) delete params.options.env[varName];
|
|
1145
1193
|
if (params.options.env.CLAUDE_CODE_USE_FOUNDRY === "1") params.options.env.ANTHROPIC_FOUNDRY_BASE_URL = proxyInstance.baseUrl;
|
|
1146
1194
|
if (params.options.env.CLAUDE_CODE_USE_BEDROCK === "1") params.options.env.ANTHROPIC_BEDROCK_BASE_URL = proxyInstance.baseUrl;
|
|
1147
|
-
|
|
1195
|
+
if (params.options.env.CLAUDE_CODE_USE_VERTEX === "1") params.options.env.ANTHROPIC_VERTEX_BASE_URL = proxyInstance.baseUrl;
|
|
1196
|
+
} else logger$13.debug("No claude proxy server available. Proceeding without proxy.");
|
|
1148
1197
|
const originalGenerator = originalQuery(params);
|
|
1149
1198
|
for await (const message of originalGenerator) {
|
|
1150
1199
|
collected.push(message);
|
|
@@ -1173,7 +1222,7 @@ var ClaudeAgentSDKInstrumentation = class extends InstrumentationBase {
|
|
|
1173
1222
|
}
|
|
1174
1223
|
manuallyInstrument(claudeAgentModule) {
|
|
1175
1224
|
if (claudeAgentModule.query && typeof claudeAgentModule.query === "function") this._wrap(claudeAgentModule, "query", this.patchQuery());
|
|
1176
|
-
else logger$
|
|
1225
|
+
else logger$13.debug("query function not found in claudeAgentSDK module, skipping instrumentation");
|
|
1177
1226
|
}
|
|
1178
1227
|
patchQuery() {
|
|
1179
1228
|
return (original) => instrumentClaudeAgentQuery(original);
|
|
@@ -1191,7 +1240,7 @@ var ClaudeAgentSDKInstrumentation = class extends InstrumentationBase {
|
|
|
1191
1240
|
//#endregion
|
|
1192
1241
|
//#region src/laminar.ts
|
|
1193
1242
|
loadEnv();
|
|
1194
|
-
const logger$
|
|
1243
|
+
const logger$12 = initializeLogger();
|
|
1195
1244
|
var Laminar = class Laminar {
|
|
1196
1245
|
static {
|
|
1197
1246
|
this.isInitialized = false;
|
|
@@ -1265,7 +1314,7 @@ var Laminar = class Laminar {
|
|
|
1265
1314
|
*/
|
|
1266
1315
|
static initialize({ projectApiKey, baseUrl, baseHttpUrl, httpPort, grpcPort, instrumentModules, disableBatch, traceExportTimeoutMillis, logLevel, maxExportBatchSize, forceHttp, sessionRecordingOptions, metadata, inheritGlobalContext, spanProcessor } = {}) {
|
|
1267
1316
|
if (this.isInitialized) {
|
|
1268
|
-
logger$
|
|
1317
|
+
logger$12.warn("Laminar has already been initialized. Skipping initialization.");
|
|
1269
1318
|
return;
|
|
1270
1319
|
}
|
|
1271
1320
|
const key = projectApiKey ?? process?.env?.LMNR_PROJECT_API_KEY;
|
|
@@ -1285,7 +1334,7 @@ var Laminar = class Laminar {
|
|
|
1285
1334
|
this.globalMetadata = metadata ?? {};
|
|
1286
1335
|
LaminarContextManager.setGlobalMetadata(this.globalMetadata);
|
|
1287
1336
|
if (inheritGlobalContext) LaminarContextManager.inheritGlobalContext = true;
|
|
1288
|
-
if (spanProcessor && !(spanProcessor instanceof LaminarSpanProcessor)) logger$
|
|
1337
|
+
if (spanProcessor && !(spanProcessor instanceof LaminarSpanProcessor)) logger$12.warn("Span processor is not a LaminarSpanProcessor. Some functionality may be impaired.");
|
|
1289
1338
|
this.isInitialized = true;
|
|
1290
1339
|
const urlWithoutSlash = url?.replace(/\/$/, "").replace(/:\d{1,5}$/g, "");
|
|
1291
1340
|
const httpUrlWithoutSlash = httpUrl?.replace(/\/$/, "").replace(/:\d{1,5}$/g, "");
|
|
@@ -1324,9 +1373,9 @@ var Laminar = class Laminar {
|
|
|
1324
1373
|
const baseContext = trace.setSpan(LaminarContextManager.getContext(), trace.wrapSpanContext(otelSpanContext));
|
|
1325
1374
|
const ctx = LaminarContextManager.setRawAssociationProperties(laminarContext, baseContext);
|
|
1326
1375
|
LaminarContextManager.pushContext(ctx);
|
|
1327
|
-
logger$
|
|
1376
|
+
logger$12.debug("Initialized Laminar parent context from LMNR_SPAN_CONTEXT.");
|
|
1328
1377
|
} catch (e) {
|
|
1329
|
-
logger$
|
|
1378
|
+
logger$12.warn("LMNR_SPAN_CONTEXT is set but could not be used: " + (e instanceof Error ? e.message : String(e)));
|
|
1330
1379
|
}
|
|
1331
1380
|
}
|
|
1332
1381
|
/**
|
|
@@ -1341,7 +1390,7 @@ var Laminar = class Laminar {
|
|
|
1341
1390
|
*/
|
|
1342
1391
|
static patch(modules) {
|
|
1343
1392
|
if (!this.isInitialized) {
|
|
1344
|
-
logger$
|
|
1393
|
+
logger$12.warn("Laminar must be initialized before patching modules. Skipping patch.");
|
|
1345
1394
|
return;
|
|
1346
1395
|
}
|
|
1347
1396
|
if (!modules || Object.keys(modules).length === 0) throw new Error("Pass at least one module to patch");
|
|
@@ -1525,6 +1574,14 @@ var Laminar = class Laminar {
|
|
|
1525
1574
|
* @param {string} options.userId - user ID to associate with the span.
|
|
1526
1575
|
* @param {string} options.sessionId - session ID to associate with the span.
|
|
1527
1576
|
* @param {Record<string, any>} options.metadata - metadata to associate with the span.
|
|
1577
|
+
* @param {boolean} options.global - when true, the span is registered on a
|
|
1578
|
+
* process-global context stack so that any subsequent `startSpan` /
|
|
1579
|
+
* `startActiveSpan` call (including from unrelated async tasks) uses it as
|
|
1580
|
+
* the parent. Use this for spans that span multiple disconnected async
|
|
1581
|
+
* callbacks — e.g. the root span of an OpenAI Agents trace, where child
|
|
1582
|
+
* spans are created from independent `TracingProcessor` callbacks that do
|
|
1583
|
+
* not share an async context. Defaults to false; the span still activates
|
|
1584
|
+
* within the current async context as usual.
|
|
1528
1585
|
* @returns The started span.
|
|
1529
1586
|
*
|
|
1530
1587
|
* @example
|
|
@@ -1555,7 +1612,7 @@ var Laminar = class Laminar {
|
|
|
1555
1612
|
* // | | bar
|
|
1556
1613
|
* // | | | openai.chat
|
|
1557
1614
|
*/
|
|
1558
|
-
static startActiveSpan({ name, input, spanType, context, parentSpanContext, tags, userId, sessionId, metadata, startTime }) {
|
|
1615
|
+
static startActiveSpan({ name, input, spanType, context, parentSpanContext, tags, userId, sessionId, metadata, startTime, global }) {
|
|
1559
1616
|
return this._startSpan({
|
|
1560
1617
|
name,
|
|
1561
1618
|
input,
|
|
@@ -1567,10 +1624,11 @@ var Laminar = class Laminar {
|
|
|
1567
1624
|
sessionId,
|
|
1568
1625
|
metadata,
|
|
1569
1626
|
activated: true,
|
|
1570
|
-
startTime
|
|
1627
|
+
startTime,
|
|
1628
|
+
global
|
|
1571
1629
|
});
|
|
1572
1630
|
}
|
|
1573
|
-
static _startSpan({ name, input, spanType, context, parentSpanContext, tags, userId, sessionId, metadata, activated, startTime }) {
|
|
1631
|
+
static _startSpan({ name, input, spanType, context, parentSpanContext, tags, userId, sessionId, metadata, activated, startTime, global }) {
|
|
1574
1632
|
let entityContext = context ?? LaminarContextManager.getContext();
|
|
1575
1633
|
let parentPath;
|
|
1576
1634
|
let parentIdsPath;
|
|
@@ -1590,9 +1648,8 @@ var Laminar = class Laminar {
|
|
|
1590
1648
|
parentSessionId = laminarContext.sessionId;
|
|
1591
1649
|
const spanContext = tryToOtelSpanContext(laminarContext);
|
|
1592
1650
|
entityContext = trace.setSpan(entityContext, trace.wrapSpanContext(spanContext));
|
|
1593
|
-
LaminarContextManager.pushContext(entityContext);
|
|
1594
1651
|
} catch (e) {
|
|
1595
|
-
logger$
|
|
1652
|
+
logger$12.warn("Failed to parse parent span context: " + (e instanceof Error ? e.message : String(e)));
|
|
1596
1653
|
}
|
|
1597
1654
|
const tagProperties = tags ? { [`${ASSOCIATION_PROPERTIES}.tags`]: Array.from(new Set(tags)) } : {};
|
|
1598
1655
|
const ctxAssociationProperties = LaminarContextManager.getAssociationProperties();
|
|
@@ -1632,6 +1689,10 @@ var Laminar = class Laminar {
|
|
|
1632
1689
|
entityContext = LaminarContextManager.setAssociationProperties(span, entityContext);
|
|
1633
1690
|
entityContext = trace.setSpan(entityContext, span);
|
|
1634
1691
|
LaminarContextManager.pushContext(entityContext);
|
|
1692
|
+
if (global) {
|
|
1693
|
+
LaminarContextManager.pushGlobalContext(entityContext);
|
|
1694
|
+
span.setGlobalActiveContext(entityContext);
|
|
1695
|
+
}
|
|
1635
1696
|
}
|
|
1636
1697
|
return span;
|
|
1637
1698
|
}
|
|
@@ -1691,13 +1752,13 @@ var Laminar = class Laminar {
|
|
|
1691
1752
|
}
|
|
1692
1753
|
static async flush() {
|
|
1693
1754
|
if (this.isInitialized) {
|
|
1694
|
-
logger$
|
|
1755
|
+
logger$12.debug("Flushing spans");
|
|
1695
1756
|
await forceFlush();
|
|
1696
1757
|
}
|
|
1697
1758
|
}
|
|
1698
1759
|
static async shutdown() {
|
|
1699
1760
|
if (this.isInitialized) {
|
|
1700
|
-
logger$
|
|
1761
|
+
logger$12.debug("Shutting down Laminar");
|
|
1701
1762
|
await forceFlush();
|
|
1702
1763
|
this.isInitialized = false;
|
|
1703
1764
|
_resetConfiguration();
|
|
@@ -1825,7 +1886,7 @@ return module.exports;
|
|
|
1825
1886
|
//#endregion
|
|
1826
1887
|
//#region src/browser/utils.ts
|
|
1827
1888
|
const LMNR_SEND_EVENTS_FUNCTION_NAME = "lmnrSendEvents";
|
|
1828
|
-
const logger$
|
|
1889
|
+
const logger$11 = initializeLogger();
|
|
1829
1890
|
/**
|
|
1830
1891
|
* If the first argument is a string, return an object with the name of the method
|
|
1831
1892
|
* and the argument as the value.
|
|
@@ -1848,7 +1909,7 @@ const takeFullSnapshot = async (page) => await page.evaluate(() => {
|
|
|
1848
1909
|
window.lmnrRrweb.record.takeFullSnapshot();
|
|
1849
1910
|
return true;
|
|
1850
1911
|
} catch (error) {
|
|
1851
|
-
logger$
|
|
1912
|
+
logger$11.error(`Error taking full snapshot: ${error instanceof Error ? error.message : String(error)}`);
|
|
1852
1913
|
return false;
|
|
1853
1914
|
}
|
|
1854
1915
|
return false;
|
|
@@ -1859,7 +1920,7 @@ const injectSessionRecorder = async (page, sessionRecordingOptions) => {
|
|
|
1859
1920
|
try {
|
|
1860
1921
|
return await script();
|
|
1861
1922
|
} catch (error) {
|
|
1862
|
-
logger$
|
|
1923
|
+
logger$11.error("Operation " + script.name + ` failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
1863
1924
|
}
|
|
1864
1925
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
1865
1926
|
}
|
|
@@ -1869,20 +1930,20 @@ const injectSessionRecorder = async (page, sessionRecordingOptions) => {
|
|
|
1869
1930
|
try {
|
|
1870
1931
|
isRrwebPresent = await castedPage.evaluate(() => typeof window.lmnrRrweb !== "undefined");
|
|
1871
1932
|
} catch (error) {
|
|
1872
|
-
logger$
|
|
1933
|
+
logger$11.debug(`ailed to check if session recorder is loaded: ${error instanceof Error ? error.message : String(error)}`);
|
|
1873
1934
|
}
|
|
1874
1935
|
if (!isRrwebPresent) {
|
|
1875
1936
|
if (!await tryRunScript(async function injectSessionRecorder() {
|
|
1876
1937
|
await castedPage.evaluate(RECORDER);
|
|
1877
1938
|
return true;
|
|
1878
1939
|
})) {
|
|
1879
|
-
logger$
|
|
1940
|
+
logger$11.error("Failed to load session recorder");
|
|
1880
1941
|
return;
|
|
1881
1942
|
}
|
|
1882
1943
|
try {
|
|
1883
1944
|
await castedPage.evaluate(injectScript, sessionRecordingOptions);
|
|
1884
1945
|
} catch (error) {
|
|
1885
|
-
logger$
|
|
1946
|
+
logger$11.debug(`Failed to inject session recorder: ${error instanceof Error ? error.message : String(error)}`);
|
|
1886
1947
|
}
|
|
1887
1948
|
}
|
|
1888
1949
|
};
|
|
@@ -2140,7 +2201,7 @@ async function sendEvents(chunk, client, chunkBuffers, sessionId, traceId) {
|
|
|
2140
2201
|
try {
|
|
2141
2202
|
const { batchId, chunkIndex, totalChunks, data } = chunk;
|
|
2142
2203
|
if (!sessionId || !traceId) {
|
|
2143
|
-
logger$
|
|
2204
|
+
logger$11.debug("Missing sessionId or traceId in chunk");
|
|
2144
2205
|
return;
|
|
2145
2206
|
}
|
|
2146
2207
|
if (!chunkBuffers.has(batchId)) chunkBuffers.set(batchId, {
|
|
@@ -2159,7 +2220,7 @@ async function sendEvents(chunk, client, chunkBuffers, sessionId, traceId) {
|
|
|
2159
2220
|
traceId,
|
|
2160
2221
|
events
|
|
2161
2222
|
}).catch((error) => {
|
|
2162
|
-
logger$
|
|
2223
|
+
logger$11.debug(`Failed to send events: ${error instanceof Error ? error.message : String(error)}`);
|
|
2163
2224
|
});
|
|
2164
2225
|
chunkBuffers.delete(batchId);
|
|
2165
2226
|
}
|
|
@@ -2167,16 +2228,16 @@ async function sendEvents(chunk, client, chunkBuffers, sessionId, traceId) {
|
|
|
2167
2228
|
const toDelete = [];
|
|
2168
2229
|
for (const [bid, buffer] of chunkBuffers.entries()) if (currentTime - buffer.timestamp > OLD_BUFFER_TIMEOUT) toDelete.push(bid);
|
|
2169
2230
|
for (const bid of toDelete) {
|
|
2170
|
-
logger$
|
|
2231
|
+
logger$11.debug(`Cleaning up incomplete chunk buffer: ${bid}`);
|
|
2171
2232
|
chunkBuffers.delete(bid);
|
|
2172
2233
|
}
|
|
2173
2234
|
} catch (error) {
|
|
2174
|
-
logger$
|
|
2235
|
+
logger$11.debug(`Could not send events: ${error instanceof Error ? error.message : String(error)}`);
|
|
2175
2236
|
}
|
|
2176
2237
|
}
|
|
2177
2238
|
//#endregion
|
|
2178
2239
|
//#region src/browser/playwright.ts
|
|
2179
|
-
const logger$
|
|
2240
|
+
const logger$10 = initializeLogger();
|
|
2180
2241
|
var PlaywrightInstrumentation = class extends InstrumentationBase {
|
|
2181
2242
|
constructor(client, sessionRecordingOptions) {
|
|
2182
2243
|
super("@lmnr/playwright-instrumentation", version, { enabled: true });
|
|
@@ -2284,7 +2345,7 @@ var PlaywrightInstrumentation = class extends InstrumentationBase {
|
|
|
2284
2345
|
try {
|
|
2285
2346
|
await injectSessionRecorder(page, this._sessionRecordingOptions);
|
|
2286
2347
|
} catch (error) {
|
|
2287
|
-
logger$
|
|
2348
|
+
logger$10.error(`Error in onLoad handler: ${error instanceof Error ? error.message : String(error)}`);
|
|
2288
2349
|
}
|
|
2289
2350
|
});
|
|
2290
2351
|
const chunkBuffers = /* @__PURE__ */ new Map();
|
|
@@ -2294,7 +2355,7 @@ var PlaywrightInstrumentation = class extends InstrumentationBase {
|
|
|
2294
2355
|
await sendEvents(chunk, this._client, chunkBuffers, sessionId, traceId);
|
|
2295
2356
|
});
|
|
2296
2357
|
} catch (error) {
|
|
2297
|
-
logger$
|
|
2358
|
+
logger$10.debug("Could not expose function " + LMNR_SEND_EVENTS_FUNCTION_NAME + `: ${error instanceof Error ? error.message : String(error)}`);
|
|
2298
2359
|
}
|
|
2299
2360
|
}
|
|
2300
2361
|
};
|
|
@@ -2719,7 +2780,7 @@ var StagehandV2Instrumentation = class extends InstrumentationBase {
|
|
|
2719
2780
|
};
|
|
2720
2781
|
//#endregion
|
|
2721
2782
|
//#region src/browser/puppeteer.ts
|
|
2722
|
-
const logger$
|
|
2783
|
+
const logger$9 = initializeLogger();
|
|
2723
2784
|
var PuppeteerInstrumentation = class extends InstrumentationBase {
|
|
2724
2785
|
constructor(client, sessionRecordingOptions) {
|
|
2725
2786
|
super("@lmnr/puppeteer-instrumentation", version, { enabled: true });
|
|
@@ -2764,10 +2825,10 @@ var PuppeteerInstrumentation = class extends InstrumentationBase {
|
|
|
2764
2825
|
context.on("targetcreated", (target) => {
|
|
2765
2826
|
target.page().then((page) => {
|
|
2766
2827
|
if (page) plugin.patchPage(page, sessionId).catch((error) => {
|
|
2767
|
-
logger$
|
|
2828
|
+
logger$9.error(`Failed to patch page: ${error instanceof Error ? error.message : String(error)}`);
|
|
2768
2829
|
});
|
|
2769
2830
|
}).catch((error) => {
|
|
2770
|
-
logger$
|
|
2831
|
+
logger$9.error(`Failed to patch page: ${error instanceof Error ? error.message : String(error)}`);
|
|
2771
2832
|
});
|
|
2772
2833
|
});
|
|
2773
2834
|
await Promise.all((await context.pages()).map((page) => plugin.patchPage(page, sessionId)));
|
|
@@ -2785,19 +2846,19 @@ var PuppeteerInstrumentation = class extends InstrumentationBase {
|
|
|
2785
2846
|
context.on("targetcreated", (target) => {
|
|
2786
2847
|
target.page().then((page) => {
|
|
2787
2848
|
if (page) plugin.patchPage(page, sessionId).catch((error) => {
|
|
2788
|
-
logger$
|
|
2849
|
+
logger$9.error(`Failed to patch page: ${error instanceof Error ? error.message : String(error)}`);
|
|
2789
2850
|
});
|
|
2790
2851
|
}).catch((error) => {
|
|
2791
|
-
logger$
|
|
2852
|
+
logger$9.error(`Failed to patch page: ${error instanceof Error ? error.message : String(error)}`);
|
|
2792
2853
|
});
|
|
2793
2854
|
});
|
|
2794
2855
|
context.on("targetchanged", (target) => {
|
|
2795
2856
|
target.page().then((page) => {
|
|
2796
2857
|
if (page) plugin.patchPage(page, sessionId).catch((error) => {
|
|
2797
|
-
logger$
|
|
2858
|
+
logger$9.error(`Failed to patch page: ${error instanceof Error ? error.message : String(error)}`);
|
|
2798
2859
|
});
|
|
2799
2860
|
}).catch((error) => {
|
|
2800
|
-
logger$
|
|
2861
|
+
logger$9.error(`Failed to patch page: ${error instanceof Error ? error.message : String(error)}`);
|
|
2801
2862
|
});
|
|
2802
2863
|
});
|
|
2803
2864
|
for (const page of await context.pages()) await plugin.patchPage(page, sessionId);
|
|
@@ -2821,7 +2882,7 @@ var PuppeteerInstrumentation = class extends InstrumentationBase {
|
|
|
2821
2882
|
const traceId = otelTraceId ? otelTraceIdToUUID(otelTraceId) : NIL_UUID;
|
|
2822
2883
|
page.on("domcontentloaded", () => {
|
|
2823
2884
|
injectSessionRecorder(page, this._sessionRecordingOptions).catch((error) => {
|
|
2824
|
-
logger$
|
|
2885
|
+
logger$9.error(`Error in onLoad handler: ${error instanceof Error ? error.message : String(error)}`);
|
|
2825
2886
|
});
|
|
2826
2887
|
});
|
|
2827
2888
|
await injectSessionRecorder(page, this._sessionRecordingOptions);
|
|
@@ -2831,13 +2892,13 @@ var PuppeteerInstrumentation = class extends InstrumentationBase {
|
|
|
2831
2892
|
await sendEvents(chunk, this._client, chunkBuffers, sessionId, traceId);
|
|
2832
2893
|
});
|
|
2833
2894
|
} catch (error) {
|
|
2834
|
-
logger$
|
|
2895
|
+
logger$9.debug("Could not expose function " + LMNR_SEND_EVENTS_FUNCTION_NAME + `: ${error instanceof Error ? error.message : String(error)}`);
|
|
2835
2896
|
}
|
|
2836
2897
|
}
|
|
2837
2898
|
};
|
|
2838
2899
|
//#endregion
|
|
2839
2900
|
//#region src/browser/stagehand/v3/constants.ts
|
|
2840
|
-
const logger$
|
|
2901
|
+
const logger$8 = initializeLogger();
|
|
2841
2902
|
const CDP_OPERATION_TIMEOUT_MS = 1e4;
|
|
2842
2903
|
const SKIP_URL_PATTERNS = [
|
|
2843
2904
|
"about:blank",
|
|
@@ -2876,7 +2937,7 @@ async function getOrCreateIsolatedWorld(page) {
|
|
|
2876
2937
|
frameId
|
|
2877
2938
|
};
|
|
2878
2939
|
} catch (error) {
|
|
2879
|
-
logger$
|
|
2940
|
+
logger$8.debug(`Failed to create isolated world: ${error instanceof Error ? error.message : String(error)}`);
|
|
2880
2941
|
return null;
|
|
2881
2942
|
}
|
|
2882
2943
|
}
|
|
@@ -2893,7 +2954,7 @@ async function isRecorderPresent(page, contextId) {
|
|
|
2893
2954
|
if (!result) return true;
|
|
2894
2955
|
return result.result?.value === true;
|
|
2895
2956
|
} catch (error) {
|
|
2896
|
-
logger$
|
|
2957
|
+
logger$8.debug(`Failed to check if recorder is present: ${error instanceof Error ? error.message : String(error)}`);
|
|
2897
2958
|
return true;
|
|
2898
2959
|
}
|
|
2899
2960
|
}
|
|
@@ -2906,21 +2967,21 @@ async function injectRecorderViaCDP(page, state, conn, sessionRecordingOptions,
|
|
|
2906
2967
|
try {
|
|
2907
2968
|
url = page.url();
|
|
2908
2969
|
} catch (error) {
|
|
2909
|
-
logger$
|
|
2970
|
+
logger$8.debug(`Failed to get page URL, page might be closed: ${error instanceof Error ? error.message : String(error)}`);
|
|
2910
2971
|
return null;
|
|
2911
2972
|
}
|
|
2912
2973
|
if (shouldSkipUrl(url)) {
|
|
2913
|
-
logger$
|
|
2974
|
+
logger$8.debug(`Skipping recorder injection for URL: ${url}`);
|
|
2914
2975
|
return null;
|
|
2915
2976
|
}
|
|
2916
2977
|
const worldResult = await getOrCreateIsolatedWorld(page);
|
|
2917
2978
|
if (!worldResult) {
|
|
2918
|
-
logger$
|
|
2979
|
+
logger$8.debug("Failed to get isolated world for page");
|
|
2919
2980
|
return null;
|
|
2920
2981
|
}
|
|
2921
2982
|
const { contextId, frameId } = worldResult;
|
|
2922
2983
|
if (await isRecorderPresent(page, contextId)) {
|
|
2923
|
-
logger$
|
|
2984
|
+
logger$8.debug("Recorder already present, skipping injection");
|
|
2924
2985
|
state.contextIdToSession.set(contextId, {
|
|
2925
2986
|
sessionId: state.sessionId,
|
|
2926
2987
|
traceId: state.traceId
|
|
@@ -2933,7 +2994,7 @@ async function injectRecorderViaCDP(page, state, conn, sessionRecordingOptions,
|
|
|
2933
2994
|
contextId
|
|
2934
2995
|
});
|
|
2935
2996
|
} catch (error) {
|
|
2936
|
-
logger$
|
|
2997
|
+
logger$8.debug(`Failed to inject rrweb: ${error instanceof Error ? error.message : String(error)}`);
|
|
2937
2998
|
return null;
|
|
2938
2999
|
}
|
|
2939
3000
|
const optionsJson = JSON.stringify(sessionRecordingOptions ?? {});
|
|
@@ -2944,14 +3005,14 @@ async function injectRecorderViaCDP(page, state, conn, sessionRecordingOptions,
|
|
|
2944
3005
|
contextId
|
|
2945
3006
|
});
|
|
2946
3007
|
} catch (error) {
|
|
2947
|
-
logger$
|
|
3008
|
+
logger$8.debug(`Failed to inject recording setup: ${error instanceof Error ? error.message : String(error)}`);
|
|
2948
3009
|
return null;
|
|
2949
3010
|
}
|
|
2950
3011
|
try {
|
|
2951
3012
|
await page.sendCDP("Runtime.addBinding", { name: "lmnrSendEvents" });
|
|
2952
|
-
logger$
|
|
3013
|
+
logger$8.debug(`Added binding 'lmnrSendEvents' for page ${frameId}, context ${contextId}`);
|
|
2953
3014
|
} catch (error) {
|
|
2954
|
-
logger$
|
|
3015
|
+
logger$8.debug(`Binding may already exist: ${error instanceof Error ? error.message : String(error)}`);
|
|
2955
3016
|
}
|
|
2956
3017
|
if (bindingHandler) try {
|
|
2957
3018
|
const pageTargetId = page.targetId();
|
|
@@ -2961,26 +3022,26 @@ async function injectRecorderViaCDP(page, state, conn, sessionRecordingOptions,
|
|
|
2961
3022
|
const sessionTyped = session;
|
|
2962
3023
|
if (sessionTyped.on) {
|
|
2963
3024
|
sessionTyped.on("Runtime.bindingCalled", bindingHandler);
|
|
2964
|
-
logger$
|
|
3025
|
+
logger$8.debug(`Set up binding handler on session ${sessionId}`);
|
|
2965
3026
|
}
|
|
2966
3027
|
} catch (error) {
|
|
2967
|
-
logger$
|
|
3028
|
+
logger$8.debug(`Failed to set up binding handler on session ${sessionId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
2968
3029
|
}
|
|
2969
3030
|
state.pageSessionHandlers.set(pageTargetId, bindingHandler);
|
|
2970
3031
|
}
|
|
2971
3032
|
} catch (error) {
|
|
2972
|
-
logger$
|
|
3033
|
+
logger$8.debug(`Failed to set up binding handler: ${error instanceof Error ? error.message : String(error)}`);
|
|
2973
3034
|
}
|
|
2974
3035
|
state.contextIdToSession.set(contextId, {
|
|
2975
3036
|
sessionId: state.sessionId,
|
|
2976
3037
|
traceId: state.traceId
|
|
2977
3038
|
});
|
|
2978
|
-
logger$
|
|
3039
|
+
logger$8.debug(`Registered context mapping: contextId=${contextId}, sessionId=${state.sessionId}`);
|
|
2979
3040
|
state.instrumentedPageIds.add(frameId);
|
|
2980
|
-
logger$
|
|
3041
|
+
logger$8.debug(`Successfully injected recorder into page ${frameId}`);
|
|
2981
3042
|
return contextId;
|
|
2982
3043
|
} catch (error) {
|
|
2983
|
-
logger$
|
|
3044
|
+
logger$8.debug(`Error injecting recorder: ${error instanceof Error ? error.message : String(error)}`);
|
|
2984
3045
|
return null;
|
|
2985
3046
|
}
|
|
2986
3047
|
}
|
|
@@ -2994,13 +3055,13 @@ function createBindingHandler(state) {
|
|
|
2994
3055
|
if (event.name !== "lmnrSendEvents") return;
|
|
2995
3056
|
const sessionInfo = state.contextIdToSession.get(event.executionContextId);
|
|
2996
3057
|
if (!sessionInfo) {
|
|
2997
|
-
logger$
|
|
3058
|
+
logger$8.debug("No session info found for context ID: " + event.executionContextId);
|
|
2998
3059
|
if (state.contextIdToSession.size > 0) {
|
|
2999
3060
|
const [, fallbackInfo] = state.contextIdToSession.entries().next().value;
|
|
3000
3061
|
if (fallbackInfo) try {
|
|
3001
3062
|
sendEvents(JSON.parse(event.payload), state.client, state.chunkBuffers, fallbackInfo.sessionId, fallbackInfo.traceId);
|
|
3002
3063
|
} catch (error) {
|
|
3003
|
-
logger$
|
|
3064
|
+
logger$8.debug(`Failed to parse binding payload: ${error instanceof Error ? error.message : String(error)}`);
|
|
3004
3065
|
}
|
|
3005
3066
|
}
|
|
3006
3067
|
return;
|
|
@@ -3008,7 +3069,7 @@ function createBindingHandler(state) {
|
|
|
3008
3069
|
try {
|
|
3009
3070
|
sendEvents(JSON.parse(event.payload), state.client, state.chunkBuffers, sessionInfo.sessionId, sessionInfo.traceId);
|
|
3010
3071
|
} catch (error) {
|
|
3011
|
-
logger$
|
|
3072
|
+
logger$8.debug(`Failed to handle binding event: ${error instanceof Error ? error.message : String(error)}`);
|
|
3012
3073
|
}
|
|
3013
3074
|
};
|
|
3014
3075
|
}
|
|
@@ -3024,10 +3085,10 @@ function createTargetCreatedHandler(context, state, sessionRecordingOptions) {
|
|
|
3024
3085
|
const pageId = page.mainFrameId();
|
|
3025
3086
|
if (!state.instrumentedPageIds.has(pageId)) await injectRecorderViaCDP(page, state, context.conn, sessionRecordingOptions, state.bindingHandler ?? void 0);
|
|
3026
3087
|
} catch (error) {
|
|
3027
|
-
logger$
|
|
3088
|
+
logger$8.debug(`Error injecting recorder into new page: ${error instanceof Error ? error.message : String(error)}`);
|
|
3028
3089
|
}
|
|
3029
3090
|
} catch (error) {
|
|
3030
|
-
logger$
|
|
3091
|
+
logger$8.debug(`Error handling target created event: ${error instanceof Error ? error.message : String(error)}`);
|
|
3031
3092
|
}
|
|
3032
3093
|
};
|
|
3033
3094
|
}
|
|
@@ -3039,7 +3100,7 @@ function createTargetInfoChangedHandler(context, state, sessionRecordingOptions)
|
|
|
3039
3100
|
if (event.targetInfo.type !== "page") return;
|
|
3040
3101
|
const url = event.targetInfo.url;
|
|
3041
3102
|
if (shouldSkipUrl(url)) return;
|
|
3042
|
-
logger$
|
|
3103
|
+
logger$8.debug(`Target URL changed to ${url}, checking if recorder injection needed`);
|
|
3043
3104
|
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
3044
3105
|
try {
|
|
3045
3106
|
for (const page of context.pages()) if (page.targetId() === event.targetInfo.targetId) {
|
|
@@ -3047,7 +3108,7 @@ function createTargetInfoChangedHandler(context, state, sessionRecordingOptions)
|
|
|
3047
3108
|
break;
|
|
3048
3109
|
}
|
|
3049
3110
|
} catch (error) {
|
|
3050
|
-
logger$
|
|
3111
|
+
logger$8.debug(`Error handling target info change: ${error instanceof Error ? error.message : String(error)}`);
|
|
3051
3112
|
}
|
|
3052
3113
|
};
|
|
3053
3114
|
}
|
|
@@ -3177,12 +3238,12 @@ var StagehandInstrumentation = class extends InstrumentationBase {
|
|
|
3177
3238
|
*/
|
|
3178
3239
|
async setupSessionRecording(stagehandInstance, sessionId, traceId) {
|
|
3179
3240
|
if (!this._client) {
|
|
3180
|
-
logger$
|
|
3241
|
+
logger$8.debug("No Laminar client available, skipping session recording setup");
|
|
3181
3242
|
return;
|
|
3182
3243
|
}
|
|
3183
3244
|
const context = stagehandInstance.context;
|
|
3184
3245
|
if (!context || !context.conn) {
|
|
3185
|
-
logger$
|
|
3246
|
+
logger$8.debug("No context or connection available, skipping session recording setup");
|
|
3186
3247
|
return;
|
|
3187
3248
|
}
|
|
3188
3249
|
const recorderState = {
|
|
@@ -3212,11 +3273,11 @@ var StagehandInstrumentation = class extends InstrumentationBase {
|
|
|
3212
3273
|
for (const page of pages) try {
|
|
3213
3274
|
if (await injectRecorderViaCDP(page, recorderState, context.conn, this._sessionRecordingOptions, bindingHandler) !== null) injectedCount++;
|
|
3214
3275
|
} catch (error) {
|
|
3215
|
-
logger$
|
|
3276
|
+
logger$8.debug(`Error injecting recorder into page: ${error instanceof Error ? error.message : String(error)}`);
|
|
3216
3277
|
}
|
|
3217
|
-
logger$
|
|
3278
|
+
logger$8.debug(`Injected session recorder into ${injectedCount} of ${pages.length} existing page(s)`);
|
|
3218
3279
|
} catch (error) {
|
|
3219
|
-
logger$
|
|
3280
|
+
logger$8.debug(`Error accessing pages for recorder injection: ${error instanceof Error ? error.message : String(error)}`);
|
|
3220
3281
|
}
|
|
3221
3282
|
}
|
|
3222
3283
|
patchStagehandClose() {
|
|
@@ -3246,12 +3307,12 @@ var StagehandInstrumentation = class extends InstrumentationBase {
|
|
|
3246
3307
|
if (recorderState.targetCreatedHandler) try {
|
|
3247
3308
|
context.conn.off("Target.targetCreated", recorderState.targetCreatedHandler);
|
|
3248
3309
|
} catch (error) {
|
|
3249
|
-
logger$
|
|
3310
|
+
logger$8.debug(`Error removing target created handler: ${error instanceof Error ? error.message : String(error)}`);
|
|
3250
3311
|
}
|
|
3251
3312
|
if (recorderState.targetInfoChangedHandler) try {
|
|
3252
3313
|
context.conn.off("Target.targetInfoChanged", recorderState.targetInfoChangedHandler);
|
|
3253
3314
|
} catch (error) {
|
|
3254
|
-
logger$
|
|
3315
|
+
logger$8.debug(`Error removing target info changed handler: ${error instanceof Error ? error.message : String(error)}`);
|
|
3255
3316
|
}
|
|
3256
3317
|
}
|
|
3257
3318
|
recorderState.contextIdToSession.clear();
|
|
@@ -3262,7 +3323,7 @@ var StagehandInstrumentation = class extends InstrumentationBase {
|
|
|
3262
3323
|
recorderState.targetCreatedHandler = null;
|
|
3263
3324
|
recorderState.targetInfoChangedHandler = null;
|
|
3264
3325
|
this.stagehandInstanceToRecorderState.delete(stagehandInstance);
|
|
3265
|
-
logger$
|
|
3326
|
+
logger$8.debug("Cleaned up session recording for Stagehand instance");
|
|
3266
3327
|
}
|
|
3267
3328
|
patchStagehandGlobalMethod(methodName, sessionId, parentSpan) {
|
|
3268
3329
|
return (original) => async function method(...args) {
|
|
@@ -3982,6 +4043,610 @@ var KernelInstrumentation = class extends InstrumentationBase {
|
|
|
3982
4043
|
this._unwrap(moduleExports.Kernel.prototype, "app");
|
|
3983
4044
|
}
|
|
3984
4045
|
};
|
|
4046
|
+
const DISABLE_OPENAI_RESPONSES_INSTRUMENTATION_CONTEXT_KEY = createContextKey("LMNR_DISABLE_OPENAI_RESPONSES_INSTRUMENTATION");
|
|
4047
|
+
const systemInstructionsStorage = new AsyncLocalStorage();
|
|
4048
|
+
const getCurrentSystemInstructions = () => systemInstructionsStorage.getStore();
|
|
4049
|
+
const runWithSystemInstructions = (value, fn) => systemInstructionsStorage.run(value, fn);
|
|
4050
|
+
const wrapStreamWithSystemInstructions = (value, source) => ({ [Symbol.asyncIterator]() {
|
|
4051
|
+
let iterator;
|
|
4052
|
+
const getIterator = () => {
|
|
4053
|
+
if (iterator === void 0) iterator = systemInstructionsStorage.run(value, () => source[Symbol.asyncIterator]());
|
|
4054
|
+
return iterator;
|
|
4055
|
+
};
|
|
4056
|
+
return {
|
|
4057
|
+
next: (..._args) => systemInstructionsStorage.run(value, () => getIterator().next()),
|
|
4058
|
+
return: (returnValue) => {
|
|
4059
|
+
const it = getIterator();
|
|
4060
|
+
return it.return ? systemInstructionsStorage.run(value, () => it.return(returnValue)) : Promise.resolve({
|
|
4061
|
+
done: true,
|
|
4062
|
+
value: returnValue
|
|
4063
|
+
});
|
|
4064
|
+
},
|
|
4065
|
+
throw: (err) => {
|
|
4066
|
+
const it = getIterator();
|
|
4067
|
+
return it.throw ? systemInstructionsStorage.run(value, () => it.throw(err)) : Promise.reject(err);
|
|
4068
|
+
}
|
|
4069
|
+
};
|
|
4070
|
+
} });
|
|
4071
|
+
const spanKind = (spanData) => {
|
|
4072
|
+
if (spanData == null) return "";
|
|
4073
|
+
return typeof spanData.type === "string" ? spanData.type : "";
|
|
4074
|
+
};
|
|
4075
|
+
const spanName = (span, spanData) => {
|
|
4076
|
+
const name = span?.name;
|
|
4077
|
+
if (typeof name === "string" && name) return name;
|
|
4078
|
+
const kind = spanKind(spanData);
|
|
4079
|
+
if (kind) {
|
|
4080
|
+
if (kind === "agent" || kind === "custom" || kind === "function" || kind === "tool") return nameFromSpanData(spanData) || `agents.${kind}`;
|
|
4081
|
+
return `agents.${kind}`;
|
|
4082
|
+
}
|
|
4083
|
+
return "agents.span";
|
|
4084
|
+
};
|
|
4085
|
+
const mapSpanType = (spanData) => {
|
|
4086
|
+
const kind = spanKind(spanData);
|
|
4087
|
+
if (kind === "generation" || kind === "response" || kind === "transcription" || kind === "speech" || kind === "speech_group") return "LLM";
|
|
4088
|
+
if (kind === "function" || kind === "tool" || kind === "mcp_list_tools" || kind === "mcp_tools" || kind === "handoff") return "TOOL";
|
|
4089
|
+
return "DEFAULT";
|
|
4090
|
+
};
|
|
4091
|
+
const nameFromSpanData = (agent) => {
|
|
4092
|
+
if (agent == null) return "";
|
|
4093
|
+
if (typeof agent === "string") return agent;
|
|
4094
|
+
if (typeof agent === "object") {
|
|
4095
|
+
if (typeof agent.name === "string") return agent.name;
|
|
4096
|
+
}
|
|
4097
|
+
return "";
|
|
4098
|
+
};
|
|
4099
|
+
const getFirstNotNull = (d, ...keys) => {
|
|
4100
|
+
if (d == null) return;
|
|
4101
|
+
for (const key of keys) {
|
|
4102
|
+
const v = d[key];
|
|
4103
|
+
if (v !== void 0 && v !== null) return v;
|
|
4104
|
+
}
|
|
4105
|
+
};
|
|
4106
|
+
const modelAsDict = (obj) => {
|
|
4107
|
+
if (obj == null) return;
|
|
4108
|
+
if (typeof obj !== "object") return;
|
|
4109
|
+
if (Array.isArray(obj)) return;
|
|
4110
|
+
return obj;
|
|
4111
|
+
};
|
|
4112
|
+
const normalizeMessages = (data, role = "user") => {
|
|
4113
|
+
if (data == null) return [];
|
|
4114
|
+
if (typeof data === "string") return [{
|
|
4115
|
+
role,
|
|
4116
|
+
content: data
|
|
4117
|
+
}];
|
|
4118
|
+
if (Array.isArray(data)) {
|
|
4119
|
+
const messages = [];
|
|
4120
|
+
for (const item of data) if (item != null && typeof item === "object" && !Array.isArray(item)) messages.push(item);
|
|
4121
|
+
else messages.push({
|
|
4122
|
+
role,
|
|
4123
|
+
content: String(item)
|
|
4124
|
+
});
|
|
4125
|
+
return messages;
|
|
4126
|
+
}
|
|
4127
|
+
if (typeof data === "object") return [data];
|
|
4128
|
+
return [{
|
|
4129
|
+
role,
|
|
4130
|
+
content: String(data)
|
|
4131
|
+
}];
|
|
4132
|
+
};
|
|
4133
|
+
//#endregion
|
|
4134
|
+
//#region src/opentelemetry-lib/instrumentation/openai-agents/messages.ts
|
|
4135
|
+
const logger$7 = initializeLogger();
|
|
4136
|
+
const setLmnrSpanIo = (lmnrSpan, inputData, outputData) => {
|
|
4137
|
+
if (inputData !== void 0 && inputData !== null) lmnrSpan.setAttribute(SPAN_INPUT, JSON.stringify(inputData));
|
|
4138
|
+
if (outputData !== void 0 && outputData !== null) lmnrSpan.setAttribute(SPAN_OUTPUT, JSON.stringify(outputData));
|
|
4139
|
+
};
|
|
4140
|
+
const setGenAiInputMessages = (lmnrSpan, inputData, systemInstructions) => {
|
|
4141
|
+
const hasInput = inputData !== void 0 && inputData !== null;
|
|
4142
|
+
if (!hasInput && !systemInstructions) return;
|
|
4143
|
+
const messages = hasInput ? normalizeMessages(inputData) : [];
|
|
4144
|
+
if (systemInstructions) messages.unshift({
|
|
4145
|
+
role: "system",
|
|
4146
|
+
content: [{
|
|
4147
|
+
type: "input_text",
|
|
4148
|
+
text: systemInstructions
|
|
4149
|
+
}]
|
|
4150
|
+
});
|
|
4151
|
+
if (messages.length > 0) lmnrSpan.setAttribute("gen_ai.input.messages", JSON.stringify(messages));
|
|
4152
|
+
};
|
|
4153
|
+
const setGenAiOutputMessages = (lmnrSpan, outputData) => {
|
|
4154
|
+
if (outputData === void 0 || outputData === null) return;
|
|
4155
|
+
const messages = normalizeMessages(outputData, "assistant");
|
|
4156
|
+
if (messages.length > 0) lmnrSpan.setAttribute("gen_ai.output.messages", JSON.stringify(messages));
|
|
4157
|
+
};
|
|
4158
|
+
const setGenAiOutputMessagesFromResponse = (lmnrSpan, response) => {
|
|
4159
|
+
if (response == null) return;
|
|
4160
|
+
let outputItems = response.output;
|
|
4161
|
+
if (!outputItems) return;
|
|
4162
|
+
const id = response.id;
|
|
4163
|
+
if (!Array.isArray(outputItems)) {
|
|
4164
|
+
logger$7.debug("Laminar OpenAI agents instrumentation, failed to parse output items. Expected array");
|
|
4165
|
+
outputItems = [];
|
|
4166
|
+
}
|
|
4167
|
+
const result = {
|
|
4168
|
+
id,
|
|
4169
|
+
object: "response",
|
|
4170
|
+
output: outputItems
|
|
4171
|
+
};
|
|
4172
|
+
lmnrSpan.setAttribute("gen_ai.output.messages", JSON.stringify(result));
|
|
4173
|
+
};
|
|
4174
|
+
const setToolDefinitionsFromResponse = (lmnrSpan, response) => {
|
|
4175
|
+
const tools = response?.tools;
|
|
4176
|
+
if (!tools || !Array.isArray(tools)) return;
|
|
4177
|
+
const toolDefs = [];
|
|
4178
|
+
for (const tool of tools) {
|
|
4179
|
+
const toolDict = modelAsDict(tool);
|
|
4180
|
+
if (!toolDict) continue;
|
|
4181
|
+
if (toolDict.type === "function") {
|
|
4182
|
+
const funcDef = { type: "function" };
|
|
4183
|
+
const functionInfo = toolDict.function ?? toolDict;
|
|
4184
|
+
const fn = { name: functionInfo.name ?? "" };
|
|
4185
|
+
const desc = functionInfo.description;
|
|
4186
|
+
if (desc) fn.description = desc;
|
|
4187
|
+
const params = functionInfo.parameters;
|
|
4188
|
+
if (params) fn.parameters = params;
|
|
4189
|
+
const strict = functionInfo.strict;
|
|
4190
|
+
if (strict !== void 0 && strict !== null) fn.strict = strict;
|
|
4191
|
+
funcDef.function = fn;
|
|
4192
|
+
toolDefs.push(funcDef);
|
|
4193
|
+
} else toolDefs.push(toolDict);
|
|
4194
|
+
}
|
|
4195
|
+
if (toolDefs.length > 0) lmnrSpan.setAttribute("gen_ai.tool.definitions", JSON.stringify(toolDefs));
|
|
4196
|
+
};
|
|
4197
|
+
const applyLlmAttributes = (lmnrSpan, data) => {
|
|
4198
|
+
if (!data) return;
|
|
4199
|
+
const model = data.model;
|
|
4200
|
+
if (model) {
|
|
4201
|
+
lmnrSpan.setAttribute(LaminarAttributes.REQUEST_MODEL, model);
|
|
4202
|
+
lmnrSpan.setAttribute(LaminarAttributes.RESPONSE_MODEL, model);
|
|
4203
|
+
lmnrSpan.setAttribute(LaminarAttributes.PROVIDER, "openai");
|
|
4204
|
+
}
|
|
4205
|
+
const usage = data.usage;
|
|
4206
|
+
if (usage != null) applyUsage(lmnrSpan, usage);
|
|
4207
|
+
let responseId = data.response_id;
|
|
4208
|
+
if (responseId == null) responseId = data.id;
|
|
4209
|
+
if (responseId != null) lmnrSpan.setAttribute("gen_ai.response.id", responseId);
|
|
4210
|
+
};
|
|
4211
|
+
const applyUsage = (lmnrSpan, usage) => {
|
|
4212
|
+
if (usage == null) return;
|
|
4213
|
+
const inputTokens = getFirstNotNull(usage, "input_tokens", "prompt_tokens", "input");
|
|
4214
|
+
const outputTokens = getFirstNotNull(usage, "output_tokens", "completion_tokens", "output");
|
|
4215
|
+
const totalTokens = getFirstNotNull(usage, "total_tokens", "total");
|
|
4216
|
+
const inputTokensDetails = getFirstNotNull(usage, "input_tokens_details", "prompt_tokens_details");
|
|
4217
|
+
const outputTokensDetails = getFirstNotNull(usage, "output_tokens_details", "completion_tokens_details");
|
|
4218
|
+
let cachedInputTokens;
|
|
4219
|
+
let reasoningOutputTokens;
|
|
4220
|
+
if (inputTokensDetails?.cached_tokens !== void 0 && inputTokensDetails?.cached_tokens !== null) cachedInputTokens = Number(inputTokensDetails.cached_tokens);
|
|
4221
|
+
if (outputTokensDetails?.reasoning_tokens !== void 0 && outputTokensDetails?.reasoning_tokens !== null) reasoningOutputTokens = Number(outputTokensDetails.reasoning_tokens);
|
|
4222
|
+
if (inputTokens !== void 0 && inputTokens !== null) lmnrSpan.setAttribute(LaminarAttributes.INPUT_TOKEN_COUNT, Number(inputTokens));
|
|
4223
|
+
if (cachedInputTokens !== void 0) lmnrSpan.setAttribute("gen_ai.usage.cache_read_input_tokens", cachedInputTokens);
|
|
4224
|
+
if (outputTokens !== void 0 && outputTokens !== null) lmnrSpan.setAttribute(LaminarAttributes.OUTPUT_TOKEN_COUNT, Number(outputTokens));
|
|
4225
|
+
if (reasoningOutputTokens !== void 0) lmnrSpan.setAttribute("gen_ai.usage.reasoning_output_tokens", reasoningOutputTokens);
|
|
4226
|
+
if (totalTokens !== void 0 && totalTokens !== null) lmnrSpan.setAttribute(LaminarAttributes.TOTAL_TOKEN_COUNT, Number(totalTokens));
|
|
4227
|
+
else if (inputTokens !== void 0 && inputTokens !== null && outputTokens !== void 0 && outputTokens !== null) lmnrSpan.setAttribute(LaminarAttributes.TOTAL_TOKEN_COUNT, Number(inputTokens) + Number(outputTokens));
|
|
4228
|
+
};
|
|
4229
|
+
const responseToLlmData = (response) => {
|
|
4230
|
+
if (response == null) return {};
|
|
4231
|
+
return {
|
|
4232
|
+
model: response.model,
|
|
4233
|
+
usage: response.usage,
|
|
4234
|
+
response_id: response.id
|
|
4235
|
+
};
|
|
4236
|
+
};
|
|
4237
|
+
//#endregion
|
|
4238
|
+
//#region src/opentelemetry-lib/instrumentation/openai-agents/span-data.ts
|
|
4239
|
+
const applySpanError = (lmnrSpan, span) => {
|
|
4240
|
+
const error = span?.error;
|
|
4241
|
+
if (!error) return;
|
|
4242
|
+
try {
|
|
4243
|
+
const message = error.message ?? String(error);
|
|
4244
|
+
lmnrSpan.setStatus({
|
|
4245
|
+
code: SpanStatusCode.ERROR,
|
|
4246
|
+
message
|
|
4247
|
+
});
|
|
4248
|
+
} catch {}
|
|
4249
|
+
};
|
|
4250
|
+
const applySpanData = (lmnrSpan, spanData) => {
|
|
4251
|
+
if (spanData == null) return;
|
|
4252
|
+
const kind = spanKind(spanData);
|
|
4253
|
+
if (kind === "agent") applyAgentSpanData(lmnrSpan, spanData);
|
|
4254
|
+
else if (kind === "function" || kind === "tool") applyFunctionSpanData(lmnrSpan, spanData);
|
|
4255
|
+
else if (kind === "generation") applyGenerationSpanData(lmnrSpan, spanData);
|
|
4256
|
+
else if (kind === "response") applyResponseSpanData(lmnrSpan, spanData);
|
|
4257
|
+
else if (kind === "handoff") applyHandoffSpanData(lmnrSpan, spanData);
|
|
4258
|
+
else if (kind === "guardrail") applyGuardrailSpanData(lmnrSpan, spanData);
|
|
4259
|
+
else if (kind === "custom") applyCustomSpanData(lmnrSpan, spanData);
|
|
4260
|
+
else if (kind === "mcp_list_tools" || kind === "mcp_tools") applyMcpSpanData(lmnrSpan, spanData);
|
|
4261
|
+
else if (kind === "speech") applySpeechSpanData(lmnrSpan, spanData);
|
|
4262
|
+
else if (kind === "transcription") applyTranscriptionSpanData(lmnrSpan, spanData);
|
|
4263
|
+
else if (kind === "speech_group") applySpeechGroupSpanData(lmnrSpan, spanData);
|
|
4264
|
+
else setLmnrSpanIo(lmnrSpan, spanData?.input, spanData?.output);
|
|
4265
|
+
};
|
|
4266
|
+
const applyAgentSpanData = (lmnrSpan, spanData) => {
|
|
4267
|
+
const res = {};
|
|
4268
|
+
const name = spanData?.name;
|
|
4269
|
+
if (name) res.name = name;
|
|
4270
|
+
const handoffs = spanData?.handoffs;
|
|
4271
|
+
if (handoffs) res.handoffs = handoffs;
|
|
4272
|
+
const tools = spanData?.tools;
|
|
4273
|
+
if (tools) res.tools = tools;
|
|
4274
|
+
const outputType = spanData?.output_type;
|
|
4275
|
+
if (outputType) res.output_type = outputType;
|
|
4276
|
+
setLmnrSpanIo(lmnrSpan, res, null);
|
|
4277
|
+
};
|
|
4278
|
+
const applyFunctionSpanData = (lmnrSpan, spanData) => {
|
|
4279
|
+
setLmnrSpanIo(lmnrSpan, spanData?.input, spanData?.output);
|
|
4280
|
+
};
|
|
4281
|
+
const applyGenerationSpanData = (lmnrSpan, spanData) => {
|
|
4282
|
+
const inputData = spanData?.input;
|
|
4283
|
+
setGenAiInputMessages(lmnrSpan, inputData, getCurrentSystemInstructions());
|
|
4284
|
+
const outputData = spanData?.output;
|
|
4285
|
+
setGenAiOutputMessages(lmnrSpan, outputData);
|
|
4286
|
+
applyLlmAttributes(lmnrSpan, {
|
|
4287
|
+
model: spanData?.model,
|
|
4288
|
+
usage: spanData?.usage,
|
|
4289
|
+
response_id: spanData?.response_id ?? spanData?.id
|
|
4290
|
+
});
|
|
4291
|
+
};
|
|
4292
|
+
const applyResponseSpanData = (lmnrSpan, spanData) => {
|
|
4293
|
+
const response = spanData?._response ?? spanData?.response;
|
|
4294
|
+
setGenAiInputMessages(lmnrSpan, spanData?._input ?? spanData?.input, getCurrentSystemInstructions());
|
|
4295
|
+
if (response != null) {
|
|
4296
|
+
setGenAiOutputMessagesFromResponse(lmnrSpan, response);
|
|
4297
|
+
setToolDefinitionsFromResponse(lmnrSpan, response);
|
|
4298
|
+
applyLlmAttributes(lmnrSpan, responseToLlmData(response));
|
|
4299
|
+
} else if (spanData?.response_id) lmnrSpan.setAttribute("gen_ai.response.id", spanData.response_id);
|
|
4300
|
+
};
|
|
4301
|
+
const applyHandoffSpanData = (lmnrSpan, spanData) => {
|
|
4302
|
+
const fromAgent = spanData?.from_agent;
|
|
4303
|
+
const toAgent = spanData?.to_agent;
|
|
4304
|
+
if (fromAgent) lmnrSpan.setAttribute("openai.agents.handoff.from", nameFromSpanData(fromAgent));
|
|
4305
|
+
if (toAgent) lmnrSpan.setAttribute("openai.agents.handoff.to", nameFromSpanData(toAgent));
|
|
4306
|
+
};
|
|
4307
|
+
const applyGuardrailSpanData = (lmnrSpan, spanData) => {
|
|
4308
|
+
const name = spanData?.name;
|
|
4309
|
+
if (name) lmnrSpan.setAttribute("openai.agents.guardrail.name", name);
|
|
4310
|
+
const triggered = spanData?.triggered;
|
|
4311
|
+
if (triggered !== void 0 && triggered !== null) lmnrSpan.setAttribute("openai.agents.guardrail.triggered", Boolean(triggered));
|
|
4312
|
+
};
|
|
4313
|
+
const applyCustomSpanData = (lmnrSpan, spanData) => {
|
|
4314
|
+
const name = spanData?.name;
|
|
4315
|
+
if (name) lmnrSpan.setAttribute("openai.agents.custom.name", name);
|
|
4316
|
+
const customData = spanData?.data;
|
|
4317
|
+
if (customData !== void 0 && customData !== null) lmnrSpan.setAttribute("openai.agents.custom.data", JSON.stringify(customData));
|
|
4318
|
+
};
|
|
4319
|
+
const applyMcpSpanData = (lmnrSpan, spanData) => {
|
|
4320
|
+
const server = spanData?.server;
|
|
4321
|
+
if (server) lmnrSpan.setAttribute("openai.agents.mcp.server", server);
|
|
4322
|
+
const result = spanData?.result;
|
|
4323
|
+
if (result !== void 0 && result !== null) lmnrSpan.setAttribute("openai.agents.mcp.result", JSON.stringify(result));
|
|
4324
|
+
};
|
|
4325
|
+
const applySpeechSpanData = (lmnrSpan, spanData) => {
|
|
4326
|
+
const model = spanData?.model;
|
|
4327
|
+
if (model) {
|
|
4328
|
+
lmnrSpan.setAttribute(LaminarAttributes.REQUEST_MODEL, model);
|
|
4329
|
+
lmnrSpan.setAttribute(LaminarAttributes.RESPONSE_MODEL, model);
|
|
4330
|
+
lmnrSpan.setAttribute(LaminarAttributes.PROVIDER, "openai");
|
|
4331
|
+
}
|
|
4332
|
+
const inputText = spanData?.input;
|
|
4333
|
+
if (inputText) setGenAiInputMessages(lmnrSpan, inputText);
|
|
4334
|
+
const outputData = spanData?.output;
|
|
4335
|
+
if (outputData) if (typeof outputData === "object" && !Array.isArray(outputData)) setGenAiOutputMessages(lmnrSpan, outputData.data);
|
|
4336
|
+
else setGenAiOutputMessages(lmnrSpan, outputData);
|
|
4337
|
+
};
|
|
4338
|
+
const applyTranscriptionSpanData = (lmnrSpan, spanData) => {
|
|
4339
|
+
const model = spanData?.model;
|
|
4340
|
+
if (model) {
|
|
4341
|
+
lmnrSpan.setAttribute(LaminarAttributes.REQUEST_MODEL, model);
|
|
4342
|
+
lmnrSpan.setAttribute(LaminarAttributes.RESPONSE_MODEL, model);
|
|
4343
|
+
lmnrSpan.setAttribute(LaminarAttributes.PROVIDER, "openai");
|
|
4344
|
+
}
|
|
4345
|
+
const inputData = spanData?.input;
|
|
4346
|
+
if (inputData) if (typeof inputData === "object" && !Array.isArray(inputData)) setGenAiInputMessages(lmnrSpan, inputData.data);
|
|
4347
|
+
else setGenAiInputMessages(lmnrSpan, inputData);
|
|
4348
|
+
const outputText = spanData?.output;
|
|
4349
|
+
if (outputText) setGenAiOutputMessages(lmnrSpan, outputText);
|
|
4350
|
+
};
|
|
4351
|
+
const applySpeechGroupSpanData = (lmnrSpan, spanData) => {
|
|
4352
|
+
const inputText = spanData?.input;
|
|
4353
|
+
if (inputText) setGenAiInputMessages(lmnrSpan, inputText);
|
|
4354
|
+
const outputText = spanData?.output;
|
|
4355
|
+
if (outputText) setGenAiOutputMessages(lmnrSpan, outputText);
|
|
4356
|
+
};
|
|
4357
|
+
//#endregion
|
|
4358
|
+
//#region src/opentelemetry-lib/instrumentation/openai-agents/processor.ts
|
|
4359
|
+
const logger$6 = initializeLogger();
|
|
4360
|
+
var LaminarAgentsTraceProcessor = class {
|
|
4361
|
+
constructor() {
|
|
4362
|
+
this.traces = /* @__PURE__ */ new Map();
|
|
4363
|
+
this.disabled = false;
|
|
4364
|
+
}
|
|
4365
|
+
start() {}
|
|
4366
|
+
async onTraceStart(agentsTrace) {
|
|
4367
|
+
if (this.disabled) return;
|
|
4368
|
+
if (!agentsTrace.traceId) return;
|
|
4369
|
+
try {
|
|
4370
|
+
const state = this.getOrCreateTrace(agentsTrace);
|
|
4371
|
+
const traceName = agentsTrace.name;
|
|
4372
|
+
if (traceName && state.rootSpan !== void 0) try {
|
|
4373
|
+
state.rootSpan.updateName(traceName);
|
|
4374
|
+
} catch {}
|
|
4375
|
+
this.applyTraceMetadata(state.rootSpan, agentsTrace);
|
|
4376
|
+
} catch (e) {
|
|
4377
|
+
logger$6.debug(`Error in onTraceStart: ${String(e)}`);
|
|
4378
|
+
}
|
|
4379
|
+
}
|
|
4380
|
+
async onTraceEnd(agentsTrace) {
|
|
4381
|
+
if (this.disabled) return;
|
|
4382
|
+
const traceId = agentsTrace.traceId;
|
|
4383
|
+
if (!traceId) return;
|
|
4384
|
+
const state = this.traces.get(traceId);
|
|
4385
|
+
if (!state || state.ended) return;
|
|
4386
|
+
state.ended = true;
|
|
4387
|
+
this.endTraceState(state);
|
|
4388
|
+
this.traces.delete(traceId);
|
|
4389
|
+
}
|
|
4390
|
+
async onSpanStart(span) {
|
|
4391
|
+
if (this.disabled) return;
|
|
4392
|
+
if (!span.traceId) return;
|
|
4393
|
+
let lmnrSpan;
|
|
4394
|
+
try {
|
|
4395
|
+
const state = this.getOrCreateTrace(span);
|
|
4396
|
+
let parentSpanContext;
|
|
4397
|
+
const spanData = span.spanData;
|
|
4398
|
+
if (spanKind(spanData) === "agent") {
|
|
4399
|
+
const thisAgentName = nameFromSpanData(spanData?.name ?? spanData);
|
|
4400
|
+
const handoffCtx = state.pendingHandoffCtxs.get(thisAgentName);
|
|
4401
|
+
if (handoffCtx !== void 0) {
|
|
4402
|
+
state.pendingHandoffCtxs.delete(thisAgentName);
|
|
4403
|
+
parentSpanContext = handoffCtx;
|
|
4404
|
+
}
|
|
4405
|
+
}
|
|
4406
|
+
if (parentSpanContext === void 0) {
|
|
4407
|
+
const parentId = span.parentId;
|
|
4408
|
+
const parentEntry = parentId != null ? state.spans.get(parentId) : void 0;
|
|
4409
|
+
const parentLmnrSpan = parentEntry !== void 0 ? parentEntry.lmnrSpan : state.rootSpan;
|
|
4410
|
+
if (parentLmnrSpan !== void 0) try {
|
|
4411
|
+
const ctx = parentLmnrSpan.getLaminarSpanContext?.();
|
|
4412
|
+
if (ctx) parentSpanContext = JSON.stringify(ctx);
|
|
4413
|
+
} catch {}
|
|
4414
|
+
}
|
|
4415
|
+
const spanType = mapSpanType(spanData);
|
|
4416
|
+
const name = spanName(span, spanData);
|
|
4417
|
+
const ctx = ROOT_CONTEXT.setValue(DISABLE_OPENAI_RESPONSES_INSTRUMENTATION_CONTEXT_KEY, true);
|
|
4418
|
+
lmnrSpan = Laminar.startSpan({
|
|
4419
|
+
name,
|
|
4420
|
+
spanType,
|
|
4421
|
+
parentSpanContext,
|
|
4422
|
+
context: ctx
|
|
4423
|
+
});
|
|
4424
|
+
const key = span.spanId;
|
|
4425
|
+
if (!key) {
|
|
4426
|
+
logger$6.debug("Span missing spanId, cannot track");
|
|
4427
|
+
try {
|
|
4428
|
+
lmnrSpan.end();
|
|
4429
|
+
} catch {}
|
|
4430
|
+
return;
|
|
4431
|
+
}
|
|
4432
|
+
let activationContext;
|
|
4433
|
+
try {
|
|
4434
|
+
activationContext = trace.setSpan(ctx, lmnrSpan);
|
|
4435
|
+
LaminarContextManager.pushContext(activationContext);
|
|
4436
|
+
} catch {
|
|
4437
|
+
activationContext = void 0;
|
|
4438
|
+
}
|
|
4439
|
+
state.spans.set(key, {
|
|
4440
|
+
lmnrSpan,
|
|
4441
|
+
agentsSpan: span,
|
|
4442
|
+
activationContext
|
|
4443
|
+
});
|
|
4444
|
+
} catch (e) {
|
|
4445
|
+
logger$6.debug(`Error in onSpanStart: ${String(e)}`);
|
|
4446
|
+
if (lmnrSpan !== void 0) try {
|
|
4447
|
+
lmnrSpan.end();
|
|
4448
|
+
} catch {}
|
|
4449
|
+
}
|
|
4450
|
+
}
|
|
4451
|
+
async onSpanEnd(span) {
|
|
4452
|
+
if (this.disabled) return;
|
|
4453
|
+
const traceId = span.traceId;
|
|
4454
|
+
if (!traceId) return;
|
|
4455
|
+
const key = span.spanId;
|
|
4456
|
+
if (!key) return;
|
|
4457
|
+
const state = this.traces.get(traceId);
|
|
4458
|
+
const entry = state?.spans.get(key);
|
|
4459
|
+
if (!entry || !state) return;
|
|
4460
|
+
state.spans.delete(key);
|
|
4461
|
+
const spanData = span.spanData;
|
|
4462
|
+
try {
|
|
4463
|
+
try {
|
|
4464
|
+
applySpanData(entry.lmnrSpan, spanData);
|
|
4465
|
+
applySpanError(entry.lmnrSpan, span);
|
|
4466
|
+
} catch {}
|
|
4467
|
+
if (spanKind(spanData) === "handoff") try {
|
|
4468
|
+
const toAgent = nameFromSpanData(spanData?.to_agent);
|
|
4469
|
+
if (toAgent) {
|
|
4470
|
+
const parentId = span.parentId;
|
|
4471
|
+
const parentEntry = parentId != null ? state.spans.get(parentId) : void 0;
|
|
4472
|
+
const parentLmnrSpan = parentEntry !== void 0 ? parentEntry.lmnrSpan : state.rootSpan;
|
|
4473
|
+
if (parentLmnrSpan !== void 0) {
|
|
4474
|
+
const handoffCtx = parentLmnrSpan.getLaminarSpanContext?.();
|
|
4475
|
+
if (handoffCtx) state.pendingHandoffCtxs.set(toAgent, JSON.stringify(handoffCtx));
|
|
4476
|
+
}
|
|
4477
|
+
}
|
|
4478
|
+
} catch {}
|
|
4479
|
+
if (entry.activationContext !== void 0) try {
|
|
4480
|
+
LaminarContextManager.removeContext(entry.activationContext);
|
|
4481
|
+
} catch {}
|
|
4482
|
+
try {
|
|
4483
|
+
entry.lmnrSpan.end();
|
|
4484
|
+
} catch {}
|
|
4485
|
+
} catch {}
|
|
4486
|
+
}
|
|
4487
|
+
async shutdown(_timeout) {
|
|
4488
|
+
this.disabled = true;
|
|
4489
|
+
const states = Array.from(this.traces.values()).filter((s) => !s.ended);
|
|
4490
|
+
for (const s of states) s.ended = true;
|
|
4491
|
+
this.traces.clear();
|
|
4492
|
+
for (const state of states) this.endTraceState(state);
|
|
4493
|
+
try {
|
|
4494
|
+
await Laminar.flush();
|
|
4495
|
+
} catch {}
|
|
4496
|
+
}
|
|
4497
|
+
async forceFlush() {
|
|
4498
|
+
try {
|
|
4499
|
+
await Laminar.flush();
|
|
4500
|
+
} catch {}
|
|
4501
|
+
}
|
|
4502
|
+
endTraceState(state) {
|
|
4503
|
+
const remaining = Array.from(state.spans.values());
|
|
4504
|
+
state.spans.clear();
|
|
4505
|
+
for (let i = remaining.length - 1; i >= 0; i--) {
|
|
4506
|
+
const entry = remaining[i];
|
|
4507
|
+
try {
|
|
4508
|
+
const spanData = entry.agentsSpan?.spanData;
|
|
4509
|
+
applySpanData(entry.lmnrSpan, spanData);
|
|
4510
|
+
applySpanError(entry.lmnrSpan, entry.agentsSpan);
|
|
4511
|
+
} catch {}
|
|
4512
|
+
if (entry.activationContext !== void 0) try {
|
|
4513
|
+
LaminarContextManager.removeContext(entry.activationContext);
|
|
4514
|
+
} catch {}
|
|
4515
|
+
try {
|
|
4516
|
+
entry.lmnrSpan.end();
|
|
4517
|
+
} catch {}
|
|
4518
|
+
}
|
|
4519
|
+
try {
|
|
4520
|
+
state.rootSpan?.end();
|
|
4521
|
+
} catch {}
|
|
4522
|
+
}
|
|
4523
|
+
getOrCreateTrace(traceOrSpan) {
|
|
4524
|
+
let traceId = traceOrSpan.traceId;
|
|
4525
|
+
if (!traceId) traceId = "unknown";
|
|
4526
|
+
const existing = this.traces.get(traceId);
|
|
4527
|
+
if (existing) return existing;
|
|
4528
|
+
const state = {
|
|
4529
|
+
rootSpan: Laminar.startSpan({
|
|
4530
|
+
name: "agents.trace",
|
|
4531
|
+
context: ROOT_CONTEXT
|
|
4532
|
+
}),
|
|
4533
|
+
spans: /* @__PURE__ */ new Map(),
|
|
4534
|
+
ended: false,
|
|
4535
|
+
pendingHandoffCtxs: /* @__PURE__ */ new Map()
|
|
4536
|
+
};
|
|
4537
|
+
this.traces.set(traceId, state);
|
|
4538
|
+
return state;
|
|
4539
|
+
}
|
|
4540
|
+
applyTraceMetadata(rootSpan, agentsTrace) {
|
|
4541
|
+
if (rootSpan === void 0) return;
|
|
4542
|
+
const metadata = {};
|
|
4543
|
+
const traceMetadata = agentsTrace.metadata;
|
|
4544
|
+
if (traceMetadata !== void 0 && traceMetadata !== null) Object.assign(metadata, traceMetadata);
|
|
4545
|
+
const groupId = agentsTrace.groupId;
|
|
4546
|
+
if (groupId) metadata["openai.agents.group_id"] = groupId;
|
|
4547
|
+
if (agentsTrace.name) metadata["openai.agents.trace_name"] = agentsTrace.name;
|
|
4548
|
+
if (Object.keys(metadata).length > 0) try {
|
|
4549
|
+
rootSpan.setTraceMetadata?.(metadata);
|
|
4550
|
+
} catch {}
|
|
4551
|
+
const sessionId = metadata.session_id;
|
|
4552
|
+
const userId = metadata.user_id;
|
|
4553
|
+
if (sessionId) try {
|
|
4554
|
+
rootSpan.setTraceSessionId?.(String(sessionId));
|
|
4555
|
+
} catch {}
|
|
4556
|
+
if (userId) try {
|
|
4557
|
+
rootSpan.setTraceUserId?.(String(userId));
|
|
4558
|
+
} catch {}
|
|
4559
|
+
}
|
|
4560
|
+
};
|
|
4561
|
+
//#endregion
|
|
4562
|
+
//#region src/opentelemetry-lib/instrumentation/openai-agents/index.ts
|
|
4563
|
+
const logger$5 = initializeLogger();
|
|
4564
|
+
const wrapGetResponse = (original) => function(request, ...rest) {
|
|
4565
|
+
const systemInstructions = request?.systemInstructions;
|
|
4566
|
+
return runWithSystemInstructions(systemInstructions, () => original.call(this, request, ...rest));
|
|
4567
|
+
};
|
|
4568
|
+
const wrapGetStreamedResponse = (original) => function(request, ...rest) {
|
|
4569
|
+
const systemInstructions = request?.systemInstructions;
|
|
4570
|
+
return wrapStreamWithSystemInstructions(systemInstructions, original.call(this, request, ...rest));
|
|
4571
|
+
};
|
|
4572
|
+
const MODEL_METHODS = ["getResponse", "getStreamedResponse"];
|
|
4573
|
+
var OpenAIAgentsInstrumentation = class extends InstrumentationBase {
|
|
4574
|
+
constructor() {
|
|
4575
|
+
super("@lmnr/openai-agents-instrumentation", version, { enabled: true });
|
|
4576
|
+
this._wrappedPrototypes = /* @__PURE__ */ new WeakSet();
|
|
4577
|
+
}
|
|
4578
|
+
init() {
|
|
4579
|
+
return [new InstrumentationNodeModuleDefinition("@openai/agents", [">=0.0.1"], this.patchAgents.bind(this), this.unpatchAgents.bind(this)), new InstrumentationNodeModuleDefinition("@openai/agents-openai", [">=0.0.1"], this.patchAgentsOpenAI.bind(this), this.unpatchAgentsOpenAI.bind(this))];
|
|
4580
|
+
}
|
|
4581
|
+
manuallyInstrument(agentsModule) {
|
|
4582
|
+
if (!agentsModule) {
|
|
4583
|
+
logger$5.debug("@openai/agents module not provided, skipping");
|
|
4584
|
+
return;
|
|
4585
|
+
}
|
|
4586
|
+
this.registerProcessor(agentsModule);
|
|
4587
|
+
this.patchModel(agentsModule);
|
|
4588
|
+
}
|
|
4589
|
+
registerProcessor(module) {
|
|
4590
|
+
if (this._processor !== void 0) return;
|
|
4591
|
+
const addTraceProcessor = module.addTraceProcessor;
|
|
4592
|
+
if (typeof addTraceProcessor !== "function") {
|
|
4593
|
+
logger$5.debug("addTraceProcessor not found in @openai/agents module");
|
|
4594
|
+
return;
|
|
4595
|
+
}
|
|
4596
|
+
try {
|
|
4597
|
+
const processor = new LaminarAgentsTraceProcessor();
|
|
4598
|
+
addTraceProcessor(processor);
|
|
4599
|
+
this._processor = processor;
|
|
4600
|
+
} catch (e) {
|
|
4601
|
+
logger$5.debug(`Failed to register Laminar Agents processor: ${String(e)}`);
|
|
4602
|
+
}
|
|
4603
|
+
}
|
|
4604
|
+
patchModel(module) {
|
|
4605
|
+
for (const cls of [module.OpenAIResponsesModel, module.OpenAIChatCompletionsModel]) {
|
|
4606
|
+
if (!cls || !cls.prototype) continue;
|
|
4607
|
+
if (this._wrappedPrototypes.has(cls.prototype)) continue;
|
|
4608
|
+
for (const method of MODEL_METHODS) {
|
|
4609
|
+
if (typeof cls.prototype[method] !== "function") continue;
|
|
4610
|
+
const wrapper = method === "getResponse" ? wrapGetResponse : wrapGetStreamedResponse;
|
|
4611
|
+
try {
|
|
4612
|
+
this._wrap(cls.prototype, method, wrapper);
|
|
4613
|
+
} catch (e) {
|
|
4614
|
+
logger$5.debug(`Failed to wrap ${method}: ${String(e)}`);
|
|
4615
|
+
}
|
|
4616
|
+
}
|
|
4617
|
+
this._wrappedPrototypes.add(cls.prototype);
|
|
4618
|
+
}
|
|
4619
|
+
}
|
|
4620
|
+
unpatchModel(module) {
|
|
4621
|
+
for (const cls of [module.OpenAIResponsesModel, module.OpenAIChatCompletionsModel]) {
|
|
4622
|
+
if (!cls || !cls.prototype) continue;
|
|
4623
|
+
if (!this._wrappedPrototypes.has(cls.prototype)) continue;
|
|
4624
|
+
for (const method of MODEL_METHODS) try {
|
|
4625
|
+
this._unwrap(cls.prototype, method);
|
|
4626
|
+
} catch {}
|
|
4627
|
+
this._wrappedPrototypes.delete(cls.prototype);
|
|
4628
|
+
}
|
|
4629
|
+
}
|
|
4630
|
+
patchAgents(moduleExports) {
|
|
4631
|
+
diag.debug("Patching @openai/agents");
|
|
4632
|
+
this.registerProcessor(moduleExports);
|
|
4633
|
+
this.patchModel(moduleExports);
|
|
4634
|
+
return moduleExports;
|
|
4635
|
+
}
|
|
4636
|
+
unpatchAgents(moduleExports) {
|
|
4637
|
+
diag.debug("Unpatching @openai/agents");
|
|
4638
|
+
this.unpatchModel(moduleExports);
|
|
4639
|
+
}
|
|
4640
|
+
patchAgentsOpenAI(moduleExports) {
|
|
4641
|
+
diag.debug("Patching @openai/agents-openai");
|
|
4642
|
+
this.patchModel(moduleExports);
|
|
4643
|
+
return moduleExports;
|
|
4644
|
+
}
|
|
4645
|
+
unpatchAgentsOpenAI(moduleExports) {
|
|
4646
|
+
diag.debug("Unpatching @openai/agents-openai");
|
|
4647
|
+
this.unpatchModel(moduleExports);
|
|
4648
|
+
}
|
|
4649
|
+
};
|
|
3985
4650
|
//#endregion
|
|
3986
4651
|
//#region src/opentelemetry-lib/instrumentation/opencode.ts
|
|
3987
4652
|
var OpencodeInstrumentation = class extends InstrumentationBase {
|
|
@@ -4129,6 +4794,7 @@ const initInstrumentations = (client, suppressContentTracing, sessionRecordingOp
|
|
|
4129
4794
|
instrumentations.push(new KernelInstrumentation());
|
|
4130
4795
|
instrumentations.push(new ClaudeAgentSDKInstrumentation());
|
|
4131
4796
|
instrumentations.push(new OpencodeInstrumentation());
|
|
4797
|
+
instrumentations.push(new OpenAIAgentsInstrumentation());
|
|
4132
4798
|
return instrumentations;
|
|
4133
4799
|
};
|
|
4134
4800
|
const manuallyInitInstrumentations = (client, instrumentModules, suppressContentTracing, sessionRecordingOptions) => {
|
|
@@ -4247,6 +4913,11 @@ const manuallyInitInstrumentations = (client, instrumentModules, suppressContent
|
|
|
4247
4913
|
instrumentations.push(opencodeInstrumentation);
|
|
4248
4914
|
opencodeInstrumentation.manuallyInstrument(instrumentModules.opencode);
|
|
4249
4915
|
}
|
|
4916
|
+
if (instrumentModules?.openAIAgents) {
|
|
4917
|
+
const openAIAgentsInstrumentation = new OpenAIAgentsInstrumentation();
|
|
4918
|
+
instrumentations.push(openAIAgentsInstrumentation);
|
|
4919
|
+
openAIAgentsInstrumentation.manuallyInstrument(instrumentModules.openAIAgents);
|
|
4920
|
+
}
|
|
4250
4921
|
return instrumentations;
|
|
4251
4922
|
};
|
|
4252
4923
|
//#endregion
|
|
@@ -4425,6 +5096,16 @@ var LaminarSpanProcessor = class LaminarSpanProcessor {
|
|
|
4425
5096
|
this._spanIdToPath.set(parentSpanId, spanPath);
|
|
4426
5097
|
this._spanIdLists.set(parentSpanId, spanIdsPath);
|
|
4427
5098
|
}
|
|
5099
|
+
/**
|
|
5100
|
+
* Drop cached path entries for a given span id. For exporters that stamp
|
|
5101
|
+
* their own span id over the SDK-allocated one after `startSpan` has fired
|
|
5102
|
+
* `onStart` — without this, `onEnd` reads the mutated id and its delete is
|
|
5103
|
+
* a no-op, so the original entry leaks one pair of map entries per span.
|
|
5104
|
+
*/
|
|
5105
|
+
dropPathInfo(spanId) {
|
|
5106
|
+
this._spanIdToPath.delete(spanId);
|
|
5107
|
+
this._spanIdLists.delete(spanId);
|
|
5108
|
+
}
|
|
4428
5109
|
clear() {
|
|
4429
5110
|
this._spanIdToPath.clear();
|
|
4430
5111
|
this._spanIdLists.clear();
|
|
@@ -5095,6 +5776,6 @@ function observeExperimentalDecorator(config) {
|
|
|
5095
5776
|
};
|
|
5096
5777
|
}
|
|
5097
5778
|
//#endregion
|
|
5098
|
-
export {
|
|
5779
|
+
export { getSpanProcessor as a, LaminarSpanProcessor as c, Laminar as d, instrumentClaudeAgentQuery as f, stringifyPromptForTelemetry as g, consumeStreamResult as h, withTracingLevel as i, getLangVersion as l, TracingLevel as m, observeDecorator as n, getTracer as o, LaminarContextManager as p, observeExperimentalDecorator as r, getTracerProvider as s, observe as t, initializeLaminarInstrumentations as u };
|
|
5099
5780
|
|
|
5100
|
-
//# sourceMappingURL=decorators-
|
|
5781
|
+
//# sourceMappingURL=decorators-BDFgXfgI.mjs.map
|