@amaster.ai/pi-telemetry 0.1.0-beta.0 → 0.1.1-beta.0

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/langfuse.js CHANGED
@@ -1,7 +1,7 @@
1
- import { createHash, randomUUID } from "node:crypto";
2
- import { Langfuse } from "langfuse";
3
- import { NoopRuntimeEventExporter, } from "./index.js";
4
- const DEFAULT_LANGFUSE_BASE_URL = "https://cloud.langfuse.com";
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+ import { Langfuse } from 'langfuse';
3
+ import { NoopRuntimeEventExporter, } from './index.js';
4
+ const DEFAULT_LANGFUSE_BASE_URL = 'https://cloud.langfuse.com';
5
5
  const DEFAULT_FLUSH_AT = 20;
6
6
  const DEFAULT_FLUSH_INTERVAL_MS = 5000;
7
7
  export class LangfuseSdkRuntimeEventExporter {
@@ -50,20 +50,20 @@ export class LangfuseSdkRuntimeEventExporter {
50
50
  const rootKey = chatSpanKey(event);
51
51
  const rootSpanId = langfuseSpanId(traceId, rootKey);
52
52
  switch (event.type) {
53
- case "chat_turn_started": {
53
+ case 'chat_turn_started': {
54
54
  const body = {
55
55
  id: rootSpanId,
56
- name: "copilot-chat-turn",
56
+ name: 'copilot-chat-turn',
57
57
  startTime: event.createdAt,
58
58
  input: event.details?.input,
59
- level: "DEFAULT",
59
+ level: 'DEFAULT',
60
60
  metadata: lifecycleMetadata(event),
61
61
  };
62
62
  const span = this.spans.get(rootKey);
63
63
  if (span) {
64
64
  span.update({
65
65
  input: event.details?.input,
66
- level: "DEFAULT",
66
+ level: 'DEFAULT',
67
67
  metadata: lifecycleMetadata(event),
68
68
  });
69
69
  }
@@ -72,37 +72,37 @@ export class LangfuseSdkRuntimeEventExporter {
72
72
  }
73
73
  break;
74
74
  }
75
- case "chat_turn_completed":
76
- case "chat_turn_failed": {
75
+ case 'chat_turn_completed':
76
+ case 'chat_turn_failed': {
77
77
  const output = event.details?.output ?? (event.error ? { error: event.error } : undefined);
78
78
  this.closeSdkSubagentBatchSpans(traceId, event);
79
79
  trace.update({
80
80
  sessionId: event.sessionId,
81
- name: "copilot-chat-turn",
81
+ name: 'copilot-chat-turn',
82
82
  output,
83
83
  metadata: lifecycleMetadata(event),
84
84
  });
85
85
  const span = this.spans.get(rootKey) ??
86
86
  trace.span({
87
87
  id: rootSpanId,
88
- name: "copilot-chat-turn",
88
+ name: 'copilot-chat-turn',
89
89
  startTime: event.createdAt,
90
90
  metadata: lifecycleMetadata(event),
91
91
  });
92
92
  span.update({
93
93
  output,
94
94
  endTime: event.createdAt,
95
- level: event.error ? "ERROR" : "DEFAULT",
95
+ level: event.error ? 'ERROR' : 'DEFAULT',
96
96
  ...(event.error ? { statusMessage: event.error } : {}),
97
97
  metadata: lifecycleMetadata(event),
98
98
  });
99
99
  this.spans.delete(rootKey);
100
100
  break;
101
101
  }
102
- case "chat_turn_steered":
103
- case "chat_turn_steer_delivered":
104
- case "chat_turn_followup_queued":
105
- case "chat_turn_followup_delivered": {
102
+ case 'chat_turn_steered':
103
+ case 'chat_turn_steer_delivered':
104
+ case 'chat_turn_followup_queued':
105
+ case 'chat_turn_followup_delivered': {
106
106
  const output = event.details?.output ?? chatInputLifecycleOutput(event);
107
107
  this.getSdkSpanParent(trace, rootKey).span({
108
108
  id: langfuseSpanId(traceId, chatInputSpanKey(event)),
@@ -111,28 +111,28 @@ export class LangfuseSdkRuntimeEventExporter {
111
111
  endTime: event.createdAt,
112
112
  input: event.details?.input,
113
113
  output,
114
- level: "DEFAULT",
114
+ level: 'DEFAULT',
115
115
  metadata: lifecycleMetadata(event),
116
116
  });
117
117
  break;
118
118
  }
119
- case "subagent_spawned":
120
- case "subagent_started": {
119
+ case 'subagent_spawned':
120
+ case 'subagent_started': {
121
121
  const key = subagentSpanKey(event);
122
122
  const rootSpan = this.ensureSdkRootSpan(trace, rootKey, event);
123
123
  const body = {
124
124
  id: langfuseSpanId(traceId, key),
125
- name: "subagent",
125
+ name: 'subagent',
126
126
  startTime: event.createdAt,
127
127
  input: event.details?.input,
128
- level: "DEFAULT",
128
+ level: 'DEFAULT',
129
129
  metadata: lifecycleMetadata(event),
130
130
  };
131
131
  const span = this.spans.get(key);
132
132
  if (span) {
133
133
  span.update({
134
134
  input: event.details?.input,
135
- level: "DEFAULT",
135
+ level: 'DEFAULT',
136
136
  metadata: lifecycleMetadata(event),
137
137
  });
138
138
  }
@@ -141,23 +141,23 @@ export class LangfuseSdkRuntimeEventExporter {
141
141
  }
142
142
  break;
143
143
  }
144
- case "subagent_completed":
145
- case "subagent_failed":
146
- case "subagent_cancelled": {
144
+ case 'subagent_completed':
145
+ case 'subagent_failed':
146
+ case 'subagent_cancelled': {
147
147
  const key = subagentSpanKey(event);
148
148
  const output = event.details?.output ?? (event.error ? { error: event.error } : undefined);
149
149
  const rootSpan = this.ensureSdkRootSpan(trace, rootKey, event);
150
150
  const span = this.spans.get(key) ??
151
151
  this.getSdkSubagentParent(trace, rootKey, event).span({
152
152
  id: langfuseSpanId(traceId, key),
153
- name: "subagent",
153
+ name: 'subagent',
154
154
  startTime: event.createdAt,
155
155
  metadata: lifecycleMetadata(event),
156
156
  });
157
157
  span.update({
158
158
  output,
159
159
  endTime: event.createdAt,
160
- level: event.error ? "ERROR" : "DEFAULT",
160
+ level: event.error ? 'ERROR' : 'DEFAULT',
161
161
  ...(event.error ? { statusMessage: event.error } : {}),
162
162
  metadata: lifecycleMetadata(event),
163
163
  });
@@ -175,20 +175,20 @@ export class LangfuseSdkRuntimeEventExporter {
175
175
  const parent = this.getSdkEventParent(trace, rootKey, event);
176
176
  const key = toolSpanKey(event);
177
177
  const id = langfuseSpanId(traceId, key);
178
- if (event.status === "started") {
178
+ if (event.status === 'started') {
179
179
  const body = {
180
180
  id,
181
181
  name: toolObservationName(event),
182
182
  startTime: event.createdAt,
183
183
  input: event.args ? { args: event.args } : undefined,
184
- level: "DEFAULT",
184
+ level: 'DEFAULT',
185
185
  metadata: toolMetadata(event),
186
186
  };
187
187
  const span = this.spans.get(key);
188
188
  if (span) {
189
189
  span.update({
190
190
  input: event.args ? { args: event.args } : undefined,
191
- level: "DEFAULT",
191
+ level: 'DEFAULT',
192
192
  metadata: toolMetadata(event),
193
193
  });
194
194
  }
@@ -208,7 +208,7 @@ export class LangfuseSdkRuntimeEventExporter {
208
208
  span.update({
209
209
  output,
210
210
  endTime: event.createdAt,
211
- level: event.error ? "ERROR" : "DEFAULT",
211
+ level: event.error ? 'ERROR' : 'DEFAULT',
212
212
  ...(event.error ? { statusMessage: event.error } : {}),
213
213
  metadata: toolMetadata(event),
214
214
  });
@@ -221,7 +221,7 @@ export class LangfuseSdkRuntimeEventExporter {
221
221
  const parent = this.getSdkEventParent(trace, rootKey, event);
222
222
  const key = llmGenerationKey(event);
223
223
  const id = langfuseSpanId(traceId, key);
224
- if (event.status === "started") {
224
+ if (event.status === 'started') {
225
225
  const body = {
226
226
  id,
227
227
  name: llmGenerationObservationName(event),
@@ -257,9 +257,11 @@ export class LangfuseSdkRuntimeEventExporter {
257
257
  generation.update({
258
258
  output: event.output ?? (event.error ? { error: event.error } : undefined),
259
259
  endTime: event.createdAt,
260
- level: event.error ? "ERROR" : "DEFAULT",
260
+ level: event.error ? 'ERROR' : 'DEFAULT',
261
261
  ...(event.error ? { statusMessage: event.error } : {}),
262
- ...(event.usage ? { usage: toLangfuseUsage(event.usage), usageDetails: toLangfuseUsageDetails(event.usage) } : {}),
262
+ ...(event.usage
263
+ ? { usage: toLangfuseUsage(event.usage), usageDetails: toLangfuseUsageDetails(event.usage) }
264
+ : {}),
263
265
  model: event.model.model,
264
266
  modelParameters: {
265
267
  provider: event.model.provider,
@@ -278,7 +280,7 @@ export class LangfuseSdkRuntimeEventExporter {
278
280
  const trace = this.client.trace({
279
281
  id: langfuseTraceId(traceId),
280
282
  sessionId: event.sessionId,
281
- name: "copilot-chat-turn",
283
+ name: 'copilot-chat-turn',
282
284
  timestamp: event.createdAt,
283
285
  input: !isToolEvent(event) && !isLlmGenerationEvent(event) ? event.details?.input : undefined,
284
286
  metadata: isToolEvent(event)
@@ -310,10 +312,10 @@ export class LangfuseSdkRuntimeEventExporter {
310
312
  }
311
313
  const batchSpan = rootSpan.span({
312
314
  id: langfuseSpanId(requireTraceId(event.traceId), batchKey),
313
- name: "subagent fan-out",
315
+ name: 'subagent fan-out',
314
316
  startTime: event.createdAt,
315
317
  input: event.details?.input,
316
- level: "DEFAULT",
318
+ level: 'DEFAULT',
317
319
  metadata: lifecycleMetadata(event),
318
320
  });
319
321
  this.spans.set(batchKey, batchSpan);
@@ -330,7 +332,7 @@ export class LangfuseSdkRuntimeEventExporter {
330
332
  }
331
333
  span.update({
332
334
  endTime: event.createdAt,
333
- level: event.error ? "ERROR" : "DEFAULT",
335
+ level: event.error ? 'ERROR' : 'DEFAULT',
334
336
  ...(event.error ? { statusMessage: event.error } : {}),
335
337
  metadata: lifecycleMetadata(event),
336
338
  });
@@ -345,7 +347,7 @@ export class LangfuseSdkRuntimeEventExporter {
345
347
  const traceId = requireTraceId(event.traceId);
346
348
  const span = trace.span({
347
349
  id: langfuseSpanId(traceId, rootKey),
348
- name: "copilot-chat-turn",
350
+ name: 'copilot-chat-turn',
349
351
  startTime: event.createdAt,
350
352
  metadata: isToolEvent(event)
351
353
  ? toolMetadata(event)
@@ -367,16 +369,18 @@ export class LangfuseHttpRuntimeEventExporter {
367
369
  flushing;
368
370
  constructor(config, fetchImpl) {
369
371
  this.config = config;
370
- this.endpoint = `${config.baseUrl.replace(/\/+$/, "")}/api/public/ingestion`;
371
- this.authHeader = `Basic ${Buffer.from(`${config.publicKey}:${config.secretKey}`).toString("base64")}`;
372
- this.fetchImpl = fetchImpl ?? (async (input, init) => {
373
- const response = await fetch(input, init);
374
- return {
375
- ok: response.ok,
376
- status: response.status,
377
- text: () => response.text(),
378
- };
379
- });
372
+ this.endpoint = `${config.baseUrl.replace(/\/+$/, '')}/api/public/ingestion`;
373
+ this.authHeader = `Basic ${Buffer.from(`${config.publicKey}:${config.secretKey}`).toString('base64')}`;
374
+ this.fetchImpl =
375
+ fetchImpl ??
376
+ (async (input, init) => {
377
+ const response = await fetch(input, init);
378
+ return {
379
+ ok: response.ok,
380
+ status: response.status,
381
+ text: () => response.text(),
382
+ };
383
+ });
380
384
  }
381
385
  async publish(event) {
382
386
  const redactedEvent = applyTelemetryRedaction(this.config, event);
@@ -432,17 +436,17 @@ export class LangfuseHttpRuntimeEventExporter {
432
436
  }
433
437
  async sendBatch(batch) {
434
438
  const response = await this.fetchImpl(this.endpoint, {
435
- method: "POST",
439
+ method: 'POST',
436
440
  headers: {
437
441
  authorization: this.authHeader,
438
- "content-type": "application/json",
439
- "x-langfuse-ingestion-version": "4",
442
+ 'content-type': 'application/json',
443
+ 'x-langfuse-ingestion-version': '4',
440
444
  },
441
445
  body: JSON.stringify({ batch }),
442
446
  });
443
447
  if (!response.ok) {
444
- const text = await response.text().catch(() => "");
445
- throw new Error(`Langfuse ingestion failed with ${response.status}${text ? `: ${text}` : ""}`);
448
+ const text = await response.text().catch(() => '');
449
+ throw new Error(`Langfuse ingestion failed with ${response.status}${text ? `: ${text}` : ''}`);
446
450
  }
447
451
  }
448
452
  }
@@ -457,14 +461,16 @@ export class OtelRuntimeEventExporter {
457
461
  constructor(config, fetchImpl) {
458
462
  this.config = config;
459
463
  this.endpoint = normalizeOtelTracesEndpoint(config.endpoint);
460
- this.fetchImpl = fetchImpl ?? (async (input, init) => {
461
- const response = await fetch(input, init);
462
- return {
463
- ok: response.ok,
464
- status: response.status,
465
- text: () => response.text(),
466
- };
467
- });
464
+ this.fetchImpl =
465
+ fetchImpl ??
466
+ (async (input, init) => {
467
+ const response = await fetch(input, init);
468
+ return {
469
+ ok: response.ok,
470
+ status: response.status,
471
+ text: () => response.text(),
472
+ };
473
+ });
468
474
  }
469
475
  async publish(event) {
470
476
  const redactedEvent = applyTelemetryRedaction(this.config, event);
@@ -521,16 +527,16 @@ export class OtelRuntimeEventExporter {
521
527
  }
522
528
  async sendSpans(spans) {
523
529
  const response = await this.fetchImpl(this.endpoint, {
524
- method: "POST",
530
+ method: 'POST',
525
531
  headers: {
526
- "content-type": "application/json",
532
+ 'content-type': 'application/json',
527
533
  ...(this.config.headers ?? {}),
528
534
  },
529
535
  body: JSON.stringify(toOtelTracePayload(spans, this.config)),
530
536
  });
531
537
  if (!response.ok) {
532
- const text = await response.text().catch(() => "");
533
- throw new Error(`${this.config.errorLabel ?? "OTEL export"} failed with ${response.status}${text ? `: ${text}` : ""}`);
538
+ const text = await response.text().catch(() => '');
539
+ throw new Error(`${this.config.errorLabel ?? 'OTEL export'} failed with ${response.status}${text ? `: ${text}` : ''}`);
534
540
  }
535
541
  }
536
542
  }
@@ -539,7 +545,7 @@ export function createRuntimeEventExporterFromEnv(env) {
539
545
  if (!config.enabled) {
540
546
  return new NoopRuntimeEventExporter();
541
547
  }
542
- if (config.transport === "sdk") {
548
+ if (config.transport === 'sdk') {
543
549
  return new LangfuseSdkRuntimeEventExporter(config);
544
550
  }
545
551
  return new LangfuseHttpRuntimeEventExporter(config);
@@ -550,18 +556,18 @@ export function resolveLangfuseConfig(env) {
550
556
  const secretKey = trim(env.LANGFUSE_SECRET_KEY);
551
557
  const baseUrl = trim(env.LANGFUSE_BASE_URL) ?? DEFAULT_LANGFUSE_BASE_URL;
552
558
  const requestedTransport = parseLangfuseTransport(env.LANGFUSE_TRANSPORT);
553
- const transport = requestedTransport ?? (publicKey && secretKey ? "sdk" : "ingestion");
559
+ const transport = requestedTransport ?? (publicKey && secretKey ? 'sdk' : 'ingestion');
554
560
  const credentialsPresent = Boolean(publicKey && secretKey);
555
561
  const serviceVersion = trim(env.TELEMETRY_SERVICE_VERSION);
556
562
  return {
557
563
  enabled: Boolean(enabled && credentialsPresent),
558
564
  transport,
559
- publicKey: publicKey ?? "",
560
- secretKey: secretKey ?? "",
565
+ publicKey: publicKey ?? '',
566
+ secretKey: secretKey ?? '',
561
567
  baseUrl,
562
568
  flushAt: parsePositiveInteger(env.LANGFUSE_FLUSH_AT, DEFAULT_FLUSH_AT),
563
569
  flushIntervalMs: parsePositiveInteger(env.LANGFUSE_FLUSH_INTERVAL_MS, DEFAULT_FLUSH_INTERVAL_MS),
564
- serviceName: trim(env.TELEMETRY_SERVICE_NAME ?? env.OTEL_SERVICE_NAME) ?? "pi-server",
570
+ serviceName: trim(env.TELEMETRY_SERVICE_NAME ?? env.OTEL_SERVICE_NAME) ?? 'pi-server',
565
571
  ...(serviceVersion ? { serviceVersion } : {}),
566
572
  includePayloads: parseBooleanWithDefault(env.TELEMETRY_INCLUDE_PAYLOADS ?? env.LANGFUSE_INCLUDE_PAYLOADS, true),
567
573
  };
@@ -581,31 +587,35 @@ export function mapRuntimeEventToLangfuse(event) {
581
587
  function mapLifecycleEventToLangfuse(event) {
582
588
  const traceId = requireTraceId(event.traceId);
583
589
  switch (event.type) {
584
- case "chat_turn_started":
585
- return [ingestionEvent("trace-create", event.createdAt, {
590
+ case 'chat_turn_started':
591
+ return [
592
+ ingestionEvent('trace-create', event.createdAt, {
586
593
  id: langfuseTraceId(traceId),
587
594
  sessionId: event.sessionId,
588
- name: "copilot-chat-turn",
595
+ name: 'copilot-chat-turn',
589
596
  timestamp: event.createdAt,
590
597
  input: event.details?.input,
591
598
  metadata: lifecycleMetadata(event),
592
- })];
593
- case "chat_turn_completed":
594
- case "chat_turn_failed": {
599
+ }),
600
+ ];
601
+ case 'chat_turn_completed':
602
+ case 'chat_turn_failed': {
595
603
  const output = event.details?.output ?? (event.error ? { error: event.error } : undefined);
596
- return [ingestionEvent("trace-update", event.createdAt, {
604
+ return [
605
+ ingestionEvent('trace-update', event.createdAt, {
597
606
  id: langfuseTraceId(traceId),
598
607
  ...(output !== undefined ? { output } : {}),
599
608
  metadata: lifecycleMetadata(event),
600
- })];
609
+ }),
610
+ ];
601
611
  }
602
- case "chat_turn_steered":
603
- case "chat_turn_steer_delivered":
604
- case "chat_turn_followup_queued":
605
- case "chat_turn_followup_delivered": {
612
+ case 'chat_turn_steered':
613
+ case 'chat_turn_steer_delivered':
614
+ case 'chat_turn_followup_queued':
615
+ case 'chat_turn_followup_delivered': {
606
616
  const spanId = langfuseSpanId(traceId, chatInputSpanKey(event));
607
617
  return [
608
- ingestionEvent("span-create", event.createdAt, {
618
+ ingestionEvent('span-create', event.createdAt, {
609
619
  id: spanId,
610
620
  traceId: langfuseTraceId(traceId),
611
621
  parentObservationId: langfuseSpanId(traceId, chatSpanKey(event)),
@@ -614,7 +624,7 @@ function mapLifecycleEventToLangfuse(event) {
614
624
  input: event.details?.input,
615
625
  metadata: lifecycleMetadata(event),
616
626
  }),
617
- ingestionEvent("span-update", event.createdAt, {
627
+ ingestionEvent('span-update', event.createdAt, {
618
628
  id: spanId,
619
629
  traceId: langfuseTraceId(traceId),
620
630
  endTime: event.createdAt,
@@ -623,43 +633,45 @@ function mapLifecycleEventToLangfuse(event) {
623
633
  }),
624
634
  ];
625
635
  }
626
- case "subagent_spawned":
627
- case "subagent_started": {
636
+ case 'subagent_spawned':
637
+ case 'subagent_started': {
628
638
  const batchKey = subagentBatchSpanKey(event);
629
639
  return [
630
640
  ...(batchKey
631
641
  ? [
632
- ingestionEvent("span-create", event.createdAt, {
642
+ ingestionEvent('span-create', event.createdAt, {
633
643
  id: langfuseSpanId(traceId, batchKey),
634
644
  traceId: langfuseTraceId(traceId),
635
645
  parentObservationId: langfuseSpanId(traceId, chatSpanKey(event)),
636
- name: "subagent fan-out",
646
+ name: 'subagent fan-out',
637
647
  startTime: event.createdAt,
638
648
  input: event.details?.input,
639
649
  metadata: lifecycleMetadata(event),
640
650
  }),
641
651
  ]
642
652
  : []),
643
- ingestionEvent("span-create", event.createdAt, {
653
+ ingestionEvent('span-create', event.createdAt, {
644
654
  id: langfuseSpanId(traceId, subagentSpanKey(event)),
645
655
  traceId: langfuseTraceId(traceId),
646
656
  parentObservationId: langfuseSpanId(traceId, batchKey ?? subagentSpawnToolSpanKey(event) ?? chatSpanKey(event)),
647
- name: "subagent",
657
+ name: 'subagent',
648
658
  startTime: event.createdAt,
649
659
  metadata: lifecycleMetadata(event),
650
660
  }),
651
661
  ];
652
662
  }
653
- case "subagent_completed":
654
- case "subagent_failed":
655
- case "subagent_cancelled":
656
- return [ingestionEvent("span-update", event.createdAt, {
663
+ case 'subagent_completed':
664
+ case 'subagent_failed':
665
+ case 'subagent_cancelled':
666
+ return [
667
+ ingestionEvent('span-update', event.createdAt, {
657
668
  id: langfuseSpanId(traceId, subagentSpanKey(event)),
658
669
  traceId: langfuseTraceId(traceId),
659
670
  endTime: event.createdAt,
660
671
  metadata: lifecycleMetadata(event),
661
672
  ...(event.error ? { output: { error: event.error } } : {}),
662
- })];
673
+ }),
674
+ ];
663
675
  default:
664
676
  return assertNever(event.type);
665
677
  }
@@ -668,8 +680,8 @@ function mapToolEventToLangfuse(event) {
668
680
  const traceId = requireTraceId(event.traceId);
669
681
  const spanId = langfuseSpanId(traceId, `tool:${event.sessionId}:${event.toolCallId}:${event.toolName}`);
670
682
  const parentObservationId = langfuseParentObservationId(traceId, event);
671
- if (event.status === "started") {
672
- return ingestionEvent("span-create", event.createdAt, {
683
+ if (event.status === 'started') {
684
+ return ingestionEvent('span-create', event.createdAt, {
673
685
  id: spanId,
674
686
  traceId: langfuseTraceId(traceId),
675
687
  parentObservationId,
@@ -679,7 +691,7 @@ function mapToolEventToLangfuse(event) {
679
691
  metadata: toolMetadata(event),
680
692
  });
681
693
  }
682
- return ingestionEvent("span-update", event.createdAt, {
694
+ return ingestionEvent('span-update', event.createdAt, {
683
695
  id: spanId,
684
696
  traceId: langfuseTraceId(traceId),
685
697
  endTime: event.createdAt,
@@ -691,8 +703,8 @@ function mapLlmGenerationEventToLangfuse(event) {
691
703
  const traceId = requireTraceId(event.traceId);
692
704
  const id = langfuseSpanId(traceId, llmGenerationKey(event));
693
705
  const parentObservationId = langfuseParentObservationId(traceId, event);
694
- if (event.status === "started") {
695
- return ingestionEvent("generation-create", event.createdAt, {
706
+ if (event.status === 'started') {
707
+ return ingestionEvent('generation-create', event.createdAt, {
696
708
  id,
697
709
  traceId: langfuseTraceId(traceId),
698
710
  parentObservationId,
@@ -707,14 +719,16 @@ function mapLlmGenerationEventToLangfuse(event) {
707
719
  metadata: llmGenerationMetadata(event),
708
720
  });
709
721
  }
710
- return ingestionEvent("generation-update", event.createdAt, {
722
+ return ingestionEvent('generation-update', event.createdAt, {
711
723
  id,
712
724
  traceId: langfuseTraceId(traceId),
713
725
  endTime: event.createdAt,
714
726
  output: event.output ?? (event.error ? { error: event.error } : undefined),
715
- level: event.error ? "ERROR" : "DEFAULT",
727
+ level: event.error ? 'ERROR' : 'DEFAULT',
716
728
  ...(event.error ? { statusMessage: event.error } : {}),
717
- ...(event.usage ? { usage: toLangfuseUsage(event.usage), usageDetails: toLangfuseUsageDetails(event.usage) } : {}),
729
+ ...(event.usage
730
+ ? { usage: toLangfuseUsage(event.usage), usageDetails: toLangfuseUsageDetails(event.usage) }
731
+ : {}),
718
732
  model: event.model.model,
719
733
  modelParameters: {
720
734
  provider: event.model.provider,
@@ -739,32 +753,32 @@ function mapLifecycleEventToOtelSpans(event, pendingStarts) {
739
753
  const rootKey = chatSpanKey(event);
740
754
  const rootSpanId = langfuseSpanId(traceId, rootKey);
741
755
  switch (event.type) {
742
- case "chat_turn_started":
756
+ case 'chat_turn_started':
743
757
  pendingStarts.set(rootKey, {
744
758
  traceId: langfuseTraceId(traceId),
745
759
  spanId: rootSpanId,
746
- name: "copilot-chat-turn",
760
+ name: 'copilot-chat-turn',
747
761
  startTime: event.createdAt,
748
762
  attributes: {
749
763
  ...lifecycleMetadata(event),
750
- ...langfuseObservationAttributes({ input: event.details?.input, level: "DEFAULT" }),
764
+ ...langfuseObservationAttributes({ input: event.details?.input, level: 'DEFAULT' }),
751
765
  ...langfuseTraceAttributes({ input: event.details?.input }),
752
766
  },
753
767
  });
754
768
  return [];
755
- case "chat_turn_completed":
756
- case "chat_turn_failed":
769
+ case 'chat_turn_completed':
770
+ case 'chat_turn_failed':
757
771
  return [
758
772
  completeOtelSpan(pendingStarts, rootKey, {
759
773
  traceId: langfuseTraceId(traceId),
760
774
  spanId: rootSpanId,
761
- name: "copilot-chat-turn",
775
+ name: 'copilot-chat-turn',
762
776
  startTime: event.createdAt,
763
777
  attributes: {
764
778
  ...lifecycleMetadata(event),
765
779
  ...langfuseObservationAttributes({
766
780
  output: event.details?.output ?? (event.error ? { error: event.error } : undefined),
767
- level: event.error ? "ERROR" : "DEFAULT",
781
+ level: event.error ? 'ERROR' : 'DEFAULT',
768
782
  }),
769
783
  ...langfuseTraceAttributes({
770
784
  output: event.details?.output ?? (event.error ? { error: event.error } : undefined),
@@ -772,10 +786,10 @@ function mapLifecycleEventToOtelSpans(event, pendingStarts) {
772
786
  },
773
787
  }, event.createdAt, event.error),
774
788
  ];
775
- case "chat_turn_steered":
776
- case "chat_turn_steer_delivered":
777
- case "chat_turn_followup_queued":
778
- case "chat_turn_followup_delivered":
789
+ case 'chat_turn_steered':
790
+ case 'chat_turn_steer_delivered':
791
+ case 'chat_turn_followup_queued':
792
+ case 'chat_turn_followup_delivered':
779
793
  return [
780
794
  {
781
795
  traceId: langfuseTraceId(traceId),
@@ -789,43 +803,43 @@ function mapLifecycleEventToOtelSpans(event, pendingStarts) {
789
803
  ...langfuseObservationAttributes({
790
804
  input: event.details?.input,
791
805
  output: event.details?.output ?? chatInputLifecycleOutput(event),
792
- level: "DEFAULT",
806
+ level: 'DEFAULT',
793
807
  }),
794
808
  },
795
809
  },
796
810
  ];
797
- case "subagent_spawned":
798
- case "subagent_started": {
811
+ case 'subagent_spawned':
812
+ case 'subagent_started': {
799
813
  const key = subagentSpanKey(event);
800
814
  pendingStarts.set(key, {
801
815
  traceId: langfuseTraceId(traceId),
802
816
  spanId: langfuseSpanId(traceId, key),
803
817
  parentSpanId: langfuseSpanId(traceId, subagentSpawnToolSpanKey(event) ?? rootKey),
804
- name: "subagent",
818
+ name: 'subagent',
805
819
  startTime: event.createdAt,
806
820
  attributes: {
807
821
  ...lifecycleMetadata(event),
808
- ...langfuseObservationAttributes({ input: event.details?.input, level: "DEFAULT" }),
822
+ ...langfuseObservationAttributes({ input: event.details?.input, level: 'DEFAULT' }),
809
823
  },
810
824
  });
811
825
  return [];
812
826
  }
813
- case "subagent_completed":
814
- case "subagent_failed":
815
- case "subagent_cancelled": {
827
+ case 'subagent_completed':
828
+ case 'subagent_failed':
829
+ case 'subagent_cancelled': {
816
830
  const key = subagentSpanKey(event);
817
831
  return [
818
832
  completeOtelSpan(pendingStarts, key, {
819
833
  traceId: langfuseTraceId(traceId),
820
834
  spanId: langfuseSpanId(traceId, key),
821
835
  parentSpanId: langfuseSpanId(traceId, subagentSpawnToolSpanKey(event) ?? rootKey),
822
- name: "subagent",
836
+ name: 'subagent',
823
837
  startTime: event.createdAt,
824
838
  attributes: {
825
839
  ...lifecycleMetadata(event),
826
840
  ...langfuseObservationAttributes({
827
841
  output: event.details?.output ?? (event.error ? { error: event.error } : undefined),
828
- level: event.error ? "ERROR" : "DEFAULT",
842
+ level: event.error ? 'ERROR' : 'DEFAULT',
829
843
  }),
830
844
  },
831
845
  }, event.createdAt, event.error),
@@ -848,17 +862,17 @@ function mapToolEventToOtelSpans(event, pendingStarts) {
848
862
  ...toolMetadata(event),
849
863
  ...langfuseObservationAttributes({
850
864
  output: event.error ? { error: event.error } : event.details,
851
- level: event.error ? "ERROR" : "DEFAULT",
865
+ level: event.error ? 'ERROR' : 'DEFAULT',
852
866
  }),
853
867
  },
854
868
  };
855
- if (event.status === "started") {
869
+ if (event.status === 'started') {
856
870
  pendingStarts.set(key, {
857
871
  ...fallbackStart,
858
872
  attributes: {
859
873
  ...fallbackStart.attributes,
860
874
  ...(event.args ? { args: event.args } : {}),
861
- ...langfuseObservationAttributes({ input: event.args, level: "DEFAULT" }),
875
+ ...langfuseObservationAttributes({ input: event.args, level: 'DEFAULT' }),
862
876
  },
863
877
  });
864
878
  return [];
@@ -876,23 +890,23 @@ function mapLlmGenerationEventToOtelSpans(event, pendingStarts) {
876
890
  startTime: event.createdAt,
877
891
  attributes: {
878
892
  ...llmGenerationMetadata(event),
879
- "langfuse.observation.type": "generation",
893
+ 'langfuse.observation.type': 'generation',
880
894
  model: event.model.model,
881
895
  provider: event.model.provider,
882
896
  ...(event.model.thinkingLevel ? { thinkingLevel: event.model.thinkingLevel } : {}),
883
897
  ...langfuseObservationAttributes({
884
898
  output: event.output ?? (event.error ? { error: event.error } : undefined),
885
- level: event.error ? "ERROR" : "DEFAULT",
899
+ level: event.error ? 'ERROR' : 'DEFAULT',
886
900
  }),
887
901
  ...(event.usage ? flattenUsageAttributes(event.usage) : {}),
888
902
  },
889
903
  };
890
- if (event.status === "started") {
904
+ if (event.status === 'started') {
891
905
  pendingStarts.set(key, {
892
906
  ...fallbackStart,
893
907
  attributes: {
894
908
  ...fallbackStart.attributes,
895
- ...langfuseObservationAttributes({ input: event.input, level: "DEFAULT" }),
909
+ ...langfuseObservationAttributes({ input: event.input, level: 'DEFAULT' }),
896
910
  },
897
911
  });
898
912
  return [];
@@ -914,33 +928,37 @@ function completeOtelSpan(pendingStarts, key, fallbackStart, endTime, error) {
914
928
  }
915
929
  function langfuseObservationAttributes(input) {
916
930
  return {
917
- "langfuse.observation.type": "span",
931
+ 'langfuse.observation.type': 'span',
918
932
  ...(input.input !== undefined
919
933
  ? {
920
- "langfuse.observation.input": toLangfuseObservationPayload(input.input),
921
- "input.value": toLangfuseObservationPayload(input.input),
934
+ 'langfuse.observation.input': toLangfuseObservationPayload(input.input),
935
+ 'input.value': toLangfuseObservationPayload(input.input),
922
936
  }
923
937
  : {}),
924
938
  ...(input.output !== undefined
925
939
  ? {
926
- "langfuse.observation.output": toLangfuseObservationPayload(input.output),
927
- "output.value": toLangfuseObservationPayload(input.output),
940
+ 'langfuse.observation.output': toLangfuseObservationPayload(input.output),
941
+ 'output.value': toLangfuseObservationPayload(input.output),
928
942
  }
929
943
  : {}),
930
- ...(input.level ? { "langfuse.observation.level": input.level } : {}),
944
+ ...(input.level ? { 'langfuse.observation.level': input.level } : {}),
931
945
  };
932
946
  }
933
947
  function langfuseTraceAttributes(input) {
934
948
  return {
935
- ...(input.input !== undefined ? { "langfuse.trace.input": toLangfuseTracePayload(input.input) } : {}),
936
- ...(input.output !== undefined ? { "langfuse.trace.output": toLangfuseTracePayload(input.output) } : {}),
949
+ ...(input.input !== undefined
950
+ ? { 'langfuse.trace.input': toLangfuseTracePayload(input.input) }
951
+ : {}),
952
+ ...(input.output !== undefined
953
+ ? { 'langfuse.trace.output': toLangfuseTracePayload(input.output) }
954
+ : {}),
937
955
  };
938
956
  }
939
957
  function toLangfuseObservationPayload(value) {
940
958
  return JSON.stringify(value);
941
959
  }
942
960
  function toLangfuseTracePayload(value) {
943
- return typeof value === "string" ? value : JSON.stringify(value);
961
+ return typeof value === 'string' ? value : JSON.stringify(value);
944
962
  }
945
963
  function chatSpanKey(event) {
946
964
  const sessionId = event.parentSessionId ?? event.sessionId;
@@ -954,7 +972,7 @@ function subagentSpanKey(event) {
954
972
  return `subagent:${event.runId ?? event.childSessionId ?? event.id}`;
955
973
  }
956
974
  function subagentBatchSpanKey(event) {
957
- const batchId = event.spawnBatchId ?? stringFromJsonObject(event.details, "spawnBatchId");
975
+ const batchId = event.spawnBatchId ?? stringFromJsonObject(event.details, 'spawnBatchId');
958
976
  return event.traceId && batchId ? `subagent-batch:${event.traceId}:${batchId}` : undefined;
959
977
  }
960
978
  function telemetryEventSubagentSpanKey(event) {
@@ -983,23 +1001,25 @@ function toolObservationName(event) {
983
1001
  }
984
1002
  function chatInputObservationName(event) {
985
1003
  const prefix = chatInputObservationPrefix(event.type);
986
- const input = typeof event.details?.input === "string" ? truncateObservationSummary(event.details.input) : undefined;
1004
+ const input = typeof event.details?.input === 'string'
1005
+ ? truncateObservationSummary(event.details.input)
1006
+ : undefined;
987
1007
  return input ? `${prefix} [${input}]` : prefix;
988
1008
  }
989
1009
  function chatInputObservationPrefix(type) {
990
- if (type === "chat_turn_steered") {
991
- return "chat-steer";
1010
+ if (type === 'chat_turn_steered') {
1011
+ return 'chat-steer';
992
1012
  }
993
- if (type === "chat_turn_steer_delivered") {
994
- return "chat-steer-delivered";
1013
+ if (type === 'chat_turn_steer_delivered') {
1014
+ return 'chat-steer-delivered';
995
1015
  }
996
- if (type === "chat_turn_followup_delivered") {
997
- return "chat-followup-delivered";
1016
+ if (type === 'chat_turn_followup_delivered') {
1017
+ return 'chat-followup-delivered';
998
1018
  }
999
- return "chat-followup";
1019
+ return 'chat-followup';
1000
1020
  }
1001
1021
  function chatInputLifecycleOutput(event) {
1002
- return event.type === "chat_turn_steer_delivered" || event.type === "chat_turn_followup_delivered"
1022
+ return event.type === 'chat_turn_steer_delivered' || event.type === 'chat_turn_followup_delivered'
1003
1023
  ? { delivered: true, turnMode: event.details?.turnMode }
1004
1024
  : { accepted: true, turnMode: event.details?.turnMode };
1005
1025
  }
@@ -1007,59 +1027,59 @@ function summarizeToolArgsForName(toolName, args) {
1007
1027
  if (!args) {
1008
1028
  return undefined;
1009
1029
  }
1010
- const pathValue = stringArg(args, "path") ?? stringArg(args, "filePath") ?? stringArg(args, "absolutePath");
1030
+ const pathValue = stringArg(args, 'path') ?? stringArg(args, 'filePath') ?? stringArg(args, 'absolutePath');
1011
1031
  if (pathValue) {
1012
1032
  return truncateObservationSummary(pathValue);
1013
1033
  }
1014
- const command = stringArg(args, "command");
1034
+ const command = stringArg(args, 'command');
1015
1035
  if (command) {
1016
1036
  return truncateObservationSummary(command);
1017
1037
  }
1018
- const query = stringArg(args, "query");
1038
+ const query = stringArg(args, 'query');
1019
1039
  if (query) {
1020
1040
  return truncateObservationSummary(query);
1021
1041
  }
1022
- const task = stringArg(args, "task");
1023
- if (task && toolName === "sessions_spawn") {
1042
+ const task = stringArg(args, 'task');
1043
+ if (task && toolName === 'sessions_spawn') {
1024
1044
  return truncateObservationSummary(task);
1025
1045
  }
1026
- const code = stringArg(args, "code");
1046
+ const code = stringArg(args, 'code');
1027
1047
  if (code) {
1028
1048
  return truncateObservationSummary(code);
1029
1049
  }
1030
- const name = stringArg(args, "name");
1031
- if (name && toolName.startsWith("mcp_")) {
1050
+ const name = stringArg(args, 'name');
1051
+ if (name && toolName.startsWith('mcp_')) {
1032
1052
  return truncateObservationSummary(name);
1033
1053
  }
1034
1054
  return undefined;
1035
1055
  }
1036
1056
  function llmGenerationObservationName(event) {
1037
- return `llm-generation [${event.runId || event.childSessionId ? "subagent" : "main"}] [${summarizeLlmGenerationInputForName(event.input)}]`;
1057
+ return `llm-generation [${event.runId || event.childSessionId ? 'subagent' : 'main'}] [${summarizeLlmGenerationInputForName(event.input)}]`;
1038
1058
  }
1039
1059
  function summarizeLlmGenerationInputForName(input) {
1040
- if (typeof input === "string") {
1060
+ if (typeof input === 'string') {
1041
1061
  return truncateObservationSummary(input);
1042
1062
  }
1043
- if (input && typeof input === "object" && !Array.isArray(input)) {
1063
+ if (input && typeof input === 'object' && !Array.isArray(input)) {
1044
1064
  const continuation = input.continuation === true;
1045
- const index = typeof input.llmGenerationIndex === "number" ? input.llmGenerationIndex : undefined;
1046
- const toolResults = typeof input.previousToolResultCount === "number" ? input.previousToolResultCount : undefined;
1065
+ const index = typeof input.llmGenerationIndex === 'number' ? input.llmGenerationIndex : undefined;
1066
+ const toolResults = typeof input.previousToolResultCount === 'number' ? input.previousToolResultCount : undefined;
1047
1067
  if (continuation) {
1048
- return truncateObservationSummary(`continuation${index !== undefined ? ` #${index}` : ""}${toolResults !== undefined ? ` after ${toolResults} tool result(s)` : ""}`);
1068
+ return truncateObservationSummary(`continuation${index !== undefined ? ` #${index}` : ''}${toolResults !== undefined ? ` after ${toolResults} tool result(s)` : ''}`);
1049
1069
  }
1050
1070
  }
1051
- return "request";
1071
+ return 'request';
1052
1072
  }
1053
1073
  function stringArg(args, key) {
1054
1074
  const value = args[key];
1055
- return typeof value === "string" && value.trim() ? value.trim() : undefined;
1075
+ return typeof value === 'string' && value.trim() ? value.trim() : undefined;
1056
1076
  }
1057
1077
  function stringFromJsonObject(value, key) {
1058
1078
  const field = value?.[key];
1059
- return typeof field === "string" && field.trim() ? field.trim() : undefined;
1079
+ return typeof field === 'string' && field.trim() ? field.trim() : undefined;
1060
1080
  }
1061
1081
  function truncateObservationSummary(value, maxLength = 90) {
1062
- const normalized = value.replace(/\s+/g, " ").trim();
1082
+ const normalized = value.replace(/\s+/g, ' ').trim();
1063
1083
  return normalized.length > maxLength ? `${normalized.slice(0, maxLength - 1)}…` : normalized;
1064
1084
  }
1065
1085
  function ensureEndAfterStart(startTime, endTime) {
@@ -1071,14 +1091,16 @@ function toOtelTracePayload(spans, config) {
1071
1091
  {
1072
1092
  resource: {
1073
1093
  attributes: [
1074
- otelAttribute("service.name", config.serviceName ?? "pi-server"),
1075
- ...(config.serviceVersion ? [otelAttribute("service.version", config.serviceVersion)] : []),
1076
- otelAttribute("telemetry.sdk.name", "@amaster.ai/pi-telemetry"),
1094
+ otelAttribute('service.name', config.serviceName ?? 'pi-server'),
1095
+ ...(config.serviceVersion
1096
+ ? [otelAttribute('service.version', config.serviceVersion)]
1097
+ : []),
1098
+ otelAttribute('telemetry.sdk.name', '@amaster.ai/pi-telemetry'),
1077
1099
  ],
1078
1100
  },
1079
1101
  scopeSpans: [
1080
1102
  {
1081
- scope: { name: "@amaster.ai/pi-telemetry", version: "0.1.0" },
1103
+ scope: { name: '@amaster.ai/pi-telemetry', version: '0.1.0' },
1082
1104
  spans: spans.map(toOtelSpanPayload),
1083
1105
  },
1084
1106
  ],
@@ -1105,13 +1127,13 @@ function otelAttribute(key, value) {
1105
1127
  return { key, value: otelAttributeValue(value) };
1106
1128
  }
1107
1129
  function otelAttributeValue(value) {
1108
- if (typeof value === "boolean") {
1130
+ if (typeof value === 'boolean') {
1109
1131
  return { boolValue: value };
1110
1132
  }
1111
- if (typeof value === "number") {
1133
+ if (typeof value === 'number') {
1112
1134
  return Number.isInteger(value) ? { intValue: String(value) } : { doubleValue: value };
1113
1135
  }
1114
- if (typeof value === "string") {
1136
+ if (typeof value === 'string') {
1115
1137
  return { stringValue: value };
1116
1138
  }
1117
1139
  return { stringValue: JSON.stringify(value) };
@@ -1121,13 +1143,13 @@ function toUnixNano(iso) {
1121
1143
  return String(BigInt(Number.isFinite(millis) ? millis : Date.now()) * 1000000n);
1122
1144
  }
1123
1145
  function normalizeOtelTracesEndpoint(endpoint) {
1124
- return endpoint.endsWith("/v1/traces") ? endpoint : `${endpoint.replace(/\/+$/, "")}/v1/traces`;
1146
+ return endpoint.endsWith('/v1/traces') ? endpoint : `${endpoint.replace(/\/+$/, '')}/v1/traces`;
1125
1147
  }
1126
1148
  function shortCorrelationId(value) {
1127
1149
  if (!value) {
1128
1150
  return undefined;
1129
1151
  }
1130
- const normalized = value.startsWith("trace:") ? value.slice("trace:".length) : value;
1152
+ const normalized = value.startsWith('trace:') ? value.slice('trace:'.length) : value;
1131
1153
  const uuid = normalized.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i)?.[0];
1132
1154
  if (uuid) {
1133
1155
  return uuid.slice(0, 8);
@@ -1141,11 +1163,14 @@ function compactSessionId(value) {
1141
1163
  if (!value) {
1142
1164
  return undefined;
1143
1165
  }
1144
- const [root, ...subagents] = value.split(":subagent:");
1166
+ const [root, ...subagents] = value.split(':subagent:');
1145
1167
  if (subagents.length === 0) {
1146
1168
  return value;
1147
1169
  }
1148
- return [root, ...subagents.map((sessionId) => `sub:${shortCorrelationId(sessionId) ?? sessionId}`)].join("/");
1170
+ return [
1171
+ root,
1172
+ ...subagents.map((sessionId) => `sub:${shortCorrelationId(sessionId) ?? sessionId}`),
1173
+ ].join('/');
1149
1174
  }
1150
1175
  function lineageMetadata(event) {
1151
1176
  const sessionId = compactSessionId(event.sessionId);
@@ -1202,7 +1227,7 @@ function toLangfuseUsage(usage) {
1202
1227
  ...(usage.input !== undefined ? { input: usage.input } : {}),
1203
1228
  ...(usage.output !== undefined ? { output: usage.output } : {}),
1204
1229
  ...(usage.totalTokens !== undefined ? { total: usage.totalTokens } : {}),
1205
- unit: "TOKENS",
1230
+ unit: 'TOKENS',
1206
1231
  ...(usage.cost?.input !== undefined ? { inputCost: usage.cost.input } : {}),
1207
1232
  ...(usage.cost?.output !== undefined ? { outputCost: usage.cost.output } : {}),
1208
1233
  ...(usage.cost?.total !== undefined ? { totalCost: usage.cost.total } : {}),
@@ -1219,12 +1244,12 @@ function toLangfuseUsageDetails(usage) {
1219
1244
  }
1220
1245
  function flattenUsageAttributes(usage) {
1221
1246
  return {
1222
- ...(usage.input !== undefined ? { "usage.input": usage.input } : {}),
1223
- ...(usage.output !== undefined ? { "usage.output": usage.output } : {}),
1224
- ...(usage.cacheRead !== undefined ? { "usage.cache_read": usage.cacheRead } : {}),
1225
- ...(usage.cacheWrite !== undefined ? { "usage.cache_write": usage.cacheWrite } : {}),
1226
- ...(usage.totalTokens !== undefined ? { "usage.total_tokens": usage.totalTokens } : {}),
1227
- ...(usage.cost?.total !== undefined ? { "usage.cost.total": usage.cost.total } : {}),
1247
+ ...(usage.input !== undefined ? { 'usage.input': usage.input } : {}),
1248
+ ...(usage.output !== undefined ? { 'usage.output': usage.output } : {}),
1249
+ ...(usage.cacheRead !== undefined ? { 'usage.cache_read': usage.cacheRead } : {}),
1250
+ ...(usage.cacheWrite !== undefined ? { 'usage.cache_write': usage.cacheWrite } : {}),
1251
+ ...(usage.totalTokens !== undefined ? { 'usage.total_tokens': usage.totalTokens } : {}),
1252
+ ...(usage.cost?.total !== undefined ? { 'usage.cost.total': usage.cost.total } : {}),
1228
1253
  };
1229
1254
  }
1230
1255
  function ingestionEvent(type, timestamp, body) {
@@ -1242,7 +1267,7 @@ function langfuseSpanId(traceId, key) {
1242
1267
  return stableHex(`span:${traceId}:${key}`, 16);
1243
1268
  }
1244
1269
  function stableHex(input, length) {
1245
- return createHash("sha256").update(input).digest("hex").slice(0, length);
1270
+ return createHash('sha256').update(input).digest('hex').slice(0, length);
1246
1271
  }
1247
1272
  function applyTelemetryRedaction(config, event) {
1248
1273
  const redacted = config.redactEvent ? config.redactEvent(event) : event;
@@ -1274,13 +1299,13 @@ function redactJsonObjectPayload(input) {
1274
1299
  return rest;
1275
1300
  }
1276
1301
  function isToolEvent(event) {
1277
- return "toolCallId" in event;
1302
+ return 'toolCallId' in event;
1278
1303
  }
1279
1304
  function isLlmGenerationEvent(event) {
1280
- return "llmGenerationId" in event;
1305
+ return 'llmGenerationId' in event;
1281
1306
  }
1282
1307
  function parseBoolean(value) {
1283
- return value === "1" || value === "true" || value === "TRUE" || value === "yes";
1308
+ return value === '1' || value === 'true' || value === 'TRUE' || value === 'yes';
1284
1309
  }
1285
1310
  function parseBooleanWithDefault(value, fallback) {
1286
1311
  if (value === undefined) {
@@ -1290,7 +1315,7 @@ function parseBooleanWithDefault(value, fallback) {
1290
1315
  }
1291
1316
  function parseLangfuseTransport(value) {
1292
1317
  const normalized = value?.trim().toLowerCase();
1293
- return normalized === "sdk" || normalized === "ingestion" ? normalized : undefined;
1318
+ return normalized === 'sdk' || normalized === 'ingestion' ? normalized : undefined;
1294
1319
  }
1295
1320
  function parsePositiveInteger(value, fallback) {
1296
1321
  const parsed = Number(value);
@@ -1305,7 +1330,7 @@ function assertNever(value) {
1305
1330
  }
1306
1331
  function requireTraceId(traceId) {
1307
1332
  if (!traceId) {
1308
- throw new Error("Telemetry event is missing traceId");
1333
+ throw new Error('Telemetry event is missing traceId');
1309
1334
  }
1310
1335
  return traceId;
1311
1336
  }