@mastra/langfuse 0.0.0-stream-vnext-usage-20250908171242 → 0.0.0-testing-cloud-studios-20260114234039

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/README.md CHANGED
@@ -10,22 +10,54 @@ npm install @mastra/langfuse
10
10
 
11
11
  ## Usage
12
12
 
13
+ ### Zero-Config Setup
14
+
15
+ The exporter automatically reads credentials from environment variables:
16
+
17
+ ```bash
18
+ # Required
19
+ LANGFUSE_PUBLIC_KEY=pk-lf-...
20
+ LANGFUSE_SECRET_KEY=sk-lf-...
21
+
22
+ # Optional - defaults to Langfuse cloud
23
+ LANGFUSE_BASE_URL=https://cloud.langfuse.com
24
+ ```
25
+
13
26
  ```typescript
14
27
  import { LangfuseExporter } from '@mastra/langfuse';
15
28
 
16
- // Use with Mastra
17
29
  const mastra = new Mastra({
18
30
  ...,
19
31
  observability: {
20
- instances: {
32
+ configs: {
21
33
  langfuse: {
22
- serviceName: 'service',
34
+ serviceName: 'my-service',
35
+ exporters: [new LangfuseExporter()],
36
+ },
37
+ },
38
+ },
39
+ });
40
+ ```
41
+
42
+ ### Explicit Configuration
43
+
44
+ You can also pass credentials directly:
45
+
46
+ ```typescript
47
+ import { LangfuseExporter } from '@mastra/langfuse';
48
+
49
+ const mastra = new Mastra({
50
+ ...,
51
+ observability: {
52
+ configs: {
53
+ langfuse: {
54
+ serviceName: 'my-service',
23
55
  exporters: [
24
56
  new LangfuseExporter({
25
- publicKey: process.env.LANGFUSE_PUBLIC_KEY,
26
- secretKey: process.env.LANGFUSE_SECRET_KEY,
27
- baseUrl: process.env.LANGFUSE_BASE_URL, // Optional - defaults to Langfuse cloud
28
- realtime: true,
57
+ publicKey: 'pk-lf-...',
58
+ secretKey: 'sk-lf-...',
59
+ baseUrl: 'https://cloud.langfuse.com', // Optional
60
+ realtime: true, // Optional - flush after each event
29
61
  }),
30
62
  ],
31
63
  },
@@ -34,16 +66,22 @@ const mastra = new Mastra({
34
66
  });
35
67
  ```
36
68
 
69
+ ### Configuration Options
70
+
71
+ | Option | Type | Description |
72
+ | ----------- | --------- | ---------------------------------------------------------------------------- |
73
+ | `publicKey` | `string` | Langfuse public key. Defaults to `LANGFUSE_PUBLIC_KEY` env var |
74
+ | `secretKey` | `string` | Langfuse secret key. Defaults to `LANGFUSE_SECRET_KEY` env var |
75
+ | `baseUrl` | `string` | Langfuse host URL. Defaults to `LANGFUSE_BASE_URL` env var or Langfuse cloud |
76
+ | `realtime` | `boolean` | Flush after each event for immediate visibility. Defaults to `false` |
77
+ | `options` | `object` | Additional options to pass to the Langfuse client |
78
+
37
79
  ## Features
38
80
 
39
- ### AI Tracing
81
+ ### Tracing
40
82
 
41
83
  - **Automatic span mapping**: Root spans become Langfuse traces
42
- - **LLM generation support**: `LLM_GENERATION` spans become Langfuse generations with token usage
84
+ - **Model generation support**: `MODEL_GENERATION` spans become Langfuse generations with token usage
43
85
  - **Type-specific metadata**: Extracts relevant metadata for each span type (agents, tools, workflows)
44
86
  - **Error tracking**: Automatic error status and message tracking
45
87
  - **Hierarchical traces**: Maintains parent-child relationships
46
-
47
- ## License
48
-
49
- Apache 2.0
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Langfuse Tracing Options Helpers
3
+ *
4
+ * These helpers integrate with the `buildTracingOptions` pattern from
5
+ * `@mastra/observability` to add Langfuse-specific tracing features.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { buildTracingOptions } from '@mastra/observability';
10
+ * import { withLangfusePrompt } from '@mastra/langfuse';
11
+ *
12
+ * const prompt = await langfuse.getPrompt('my-prompt');
13
+ *
14
+ * const agent = new Agent({
15
+ * defaultGenerateOptions: {
16
+ * tracingOptions: buildTracingOptions(withLangfusePrompt(prompt)),
17
+ * },
18
+ * });
19
+ * ```
20
+ */
21
+ import type { TracingOptionsUpdater } from '@mastra/observability';
22
+ /**
23
+ * Langfuse prompt input - accepts either a Langfuse SDK prompt object
24
+ * or manual fields.
25
+ */
26
+ export interface LangfusePromptInput {
27
+ /** Prompt name */
28
+ name?: string;
29
+ /** Prompt version */
30
+ version?: number;
31
+ /** Prompt UUID */
32
+ id?: string;
33
+ }
34
+ /**
35
+ * Adds Langfuse prompt metadata to the tracing options
36
+ * to enable Langfuse Prompt Tracing.
37
+ *
38
+ * The metadata is added under `metadata.langfuse.prompt` and includes:
39
+ * - `name` - Prompt name
40
+ * - `version` - Prompt version
41
+ * - `id` - Prompt UUID
42
+ *
43
+ * All fields are deeply merged with any existing metadata.
44
+ *
45
+ * @param prompt - A Langfuse prompt object (from `langfuse.getPrompt()`) or manual fields
46
+ * @returns A TracingOptionsUpdater function for use with `buildTracingOptions`
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * import { buildTracingOptions } from '@mastra/observability';
51
+ * import { withLangfusePrompt } from '@mastra/langfuse';
52
+ * import { Langfuse } from 'langfuse';
53
+ *
54
+ * const langfuse = new Langfuse();
55
+ * const prompt = await langfuse.getPrompt('customer-support');
56
+ *
57
+ * // Use with buildTracingOptions
58
+ * const tracingOptions = buildTracingOptions(
59
+ * withLangfusePrompt(prompt),
60
+ * );
61
+ *
62
+ * // Or directly in agent config
63
+ * const agent = new Agent({
64
+ * name: 'support-agent',
65
+ * instructions: prompt.prompt,
66
+ * model: openai('gpt-4o'),
67
+ * defaultGenerateOptions: {
68
+ * tracingOptions: buildTracingOptions(withLangfusePrompt(prompt)),
69
+ * },
70
+ * });
71
+ *
72
+ * // Manual fields also work
73
+ * const tracingOptions = buildTracingOptions(
74
+ * withLangfusePrompt({ name: 'my-prompt', version: 1 }),
75
+ * );
76
+ * ```
77
+ */
78
+ export declare function withLangfusePrompt(prompt: LangfusePromptInput): TracingOptionsUpdater;
79
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAEnE;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,kBAAkB;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kBAAkB;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,mBAAmB,GAAG,qBAAqB,CAerF"}
package/dist/index.cjs CHANGED
@@ -1,51 +1,79 @@
1
1
  'use strict';
2
2
 
3
- var aiTracing = require('@mastra/core/ai-tracing');
4
- var logger = require('@mastra/core/logger');
3
+ var observability$1 = require('@mastra/core/observability');
4
+ var utils = require('@mastra/core/utils');
5
+ var observability = require('@mastra/observability');
5
6
  var langfuse = require('langfuse');
6
7
 
7
- // src/ai-tracing.ts
8
- var LangfuseExporter = class {
8
+ // src/tracing.ts
9
+ function formatUsageMetrics(usage) {
10
+ if (!usage) return {};
11
+ const metrics = {};
12
+ if (usage.inputTokens !== void 0) {
13
+ metrics.input = usage.inputTokens;
14
+ if (usage.inputDetails?.cacheWrite !== void 0) {
15
+ metrics.cache_write_input_tokens = usage.inputDetails.cacheWrite;
16
+ metrics.input -= metrics.cache_write_input_tokens;
17
+ }
18
+ }
19
+ if (usage.inputDetails?.cacheRead !== void 0) {
20
+ metrics.cache_read_input_tokens = usage.inputDetails.cacheRead;
21
+ }
22
+ if (usage.outputTokens !== void 0) {
23
+ metrics.output = usage.outputTokens;
24
+ }
25
+ if (usage.outputDetails?.reasoning !== void 0) {
26
+ metrics.reasoning = usage.outputDetails.reasoning;
27
+ }
28
+ if (metrics.input && metrics.output) {
29
+ metrics.total = metrics.input + metrics.output;
30
+ if (metrics.cache_write_input_tokens) {
31
+ metrics.total += metrics.cache_write_input_tokens;
32
+ }
33
+ }
34
+ return metrics;
35
+ }
36
+ var LangfuseExporter = class extends observability.BaseExporter {
9
37
  name = "langfuse";
10
38
  client;
11
39
  realtime;
12
40
  traceMap = /* @__PURE__ */ new Map();
13
- logger;
14
- constructor(config) {
41
+ constructor(config = {}) {
42
+ super(config);
15
43
  this.realtime = config.realtime ?? false;
16
- this.logger = new logger.ConsoleLogger({ level: config.logLevel ?? "warn" });
17
- if (!config.publicKey || !config.secretKey) {
18
- this.logger.error("LangfuseExporter: Missing required credentials, exporter will be disabled", {
19
- hasPublicKey: !!config.publicKey,
20
- hasSecretKey: !!config.secretKey
21
- });
44
+ const publicKey = config.publicKey ?? process.env.LANGFUSE_PUBLIC_KEY;
45
+ const secretKey = config.secretKey ?? process.env.LANGFUSE_SECRET_KEY;
46
+ const baseUrl = config.baseUrl ?? process.env.LANGFUSE_BASE_URL;
47
+ if (!publicKey || !secretKey) {
48
+ const publicKeySource = config.publicKey ? "from config" : process.env.LANGFUSE_PUBLIC_KEY ? "from env" : "missing";
49
+ const secretKeySource = config.secretKey ? "from config" : process.env.LANGFUSE_SECRET_KEY ? "from env" : "missing";
50
+ this.setDisabled(
51
+ `Missing required credentials (publicKey: ${publicKeySource}, secretKey: ${secretKeySource}). Set LANGFUSE_PUBLIC_KEY and LANGFUSE_SECRET_KEY environment variables or pass them in config.`
52
+ );
22
53
  this.client = null;
23
54
  return;
24
55
  }
25
56
  this.client = new langfuse.Langfuse({
26
- publicKey: config.publicKey,
27
- secretKey: config.secretKey,
28
- baseUrl: config.baseUrl,
57
+ publicKey,
58
+ secretKey,
59
+ baseUrl,
29
60
  ...config.options
30
61
  });
31
62
  }
32
- async exportEvent(event) {
33
- if (!this.client) {
34
- return;
35
- }
36
- if (event.span.isEvent) {
37
- await this.handleEventSpan(event.span);
63
+ async _exportTracingEvent(event) {
64
+ if (event.exportedSpan.isEvent) {
65
+ await this.handleEventSpan(event.exportedSpan);
38
66
  return;
39
67
  }
40
68
  switch (event.type) {
41
69
  case "span_started":
42
- await this.handleSpanStarted(event.span);
70
+ await this.handleSpanStarted(event.exportedSpan);
43
71
  break;
44
72
  case "span_updated":
45
- await this.handleSpanUpdateOrEnd(event.span, false);
73
+ await this.handleSpanUpdateOrEnd(event.exportedSpan, false);
46
74
  break;
47
75
  case "span_ended":
48
- await this.handleSpanUpdateOrEnd(event.span, true);
76
+ await this.handleSpanUpdateOrEnd(event.exportedSpan, true);
49
77
  break;
50
78
  }
51
79
  if (this.realtime) {
@@ -61,13 +89,21 @@ var LangfuseExporter = class {
61
89
  if (!traceData) {
62
90
  return;
63
91
  }
92
+ if (!span.isRootSpan) {
93
+ const langfuseData = span.metadata?.langfuse;
94
+ traceData.spanMetadata.set(span.id, {
95
+ parentSpanId: span.parentSpanId,
96
+ langfusePrompt: langfuseData?.prompt
97
+ });
98
+ }
64
99
  const langfuseParent = this.getLangfuseParent({ traceData, span, method });
65
100
  if (!langfuseParent) {
66
101
  return;
67
102
  }
68
- const payload = this.buildSpanPayload(span, true);
69
- const langfuseSpan = span.type === aiTracing.AISpanType.LLM_GENERATION ? langfuseParent.generation(payload) : langfuseParent.span(payload);
103
+ const payload = this.buildSpanPayload(span, true, traceData);
104
+ const langfuseSpan = span.type === observability$1.SpanType.MODEL_GENERATION ? langfuseParent.generation(payload) : langfuseParent.span(payload);
70
105
  traceData.spans.set(span.id, langfuseSpan);
106
+ traceData.activeSpans.add(span.id);
71
107
  }
72
108
  async handleSpanUpdateOrEnd(span, isEnd) {
73
109
  const method = isEnd ? "handleSpanEnd" : "handleSpanUpdate";
@@ -77,21 +113,33 @@ var LangfuseExporter = class {
77
113
  }
78
114
  const langfuseSpan = traceData.spans.get(span.id);
79
115
  if (!langfuseSpan) {
116
+ if (isEnd && span.isEvent) {
117
+ traceData.activeSpans.delete(span.id);
118
+ if (traceData.activeSpans.size === 0) {
119
+ this.traceMap.delete(span.traceId);
120
+ }
121
+ return;
122
+ }
80
123
  this.logger.warn("Langfuse exporter: No Langfuse span found for span update/end", {
81
124
  traceId: span.traceId,
82
125
  spanId: span.id,
83
126
  spanName: span.name,
84
127
  spanType: span.type,
85
128
  isRootSpan: span.isRootSpan,
86
- parentSpanId: span.parent?.id,
129
+ parentSpanId: span.parentSpanId,
87
130
  method
88
131
  });
89
132
  return;
90
133
  }
91
- langfuseSpan.update(this.buildSpanPayload(span, false));
92
- if (isEnd && span.isRootSpan) {
93
- traceData.trace.update({ output: span.output });
94
- this.traceMap.delete(span.traceId);
134
+ langfuseSpan.update(this.buildSpanPayload(span, false, traceData));
135
+ if (isEnd) {
136
+ traceData.activeSpans.delete(span.id);
137
+ if (span.isRootSpan) {
138
+ traceData.trace.update({ output: span.output });
139
+ }
140
+ if (traceData.activeSpans.size === 0) {
141
+ this.traceMap.delete(span.traceId);
142
+ }
95
143
  }
96
144
  }
97
145
  async handleEventSpan(span) {
@@ -113,13 +161,37 @@ var LangfuseExporter = class {
113
161
  if (!langfuseParent) {
114
162
  return;
115
163
  }
116
- const payload = this.buildSpanPayload(span, true);
164
+ const payload = this.buildSpanPayload(span, true, traceData);
117
165
  const langfuseEvent = langfuseParent.event(payload);
118
166
  traceData.events.set(span.id, langfuseEvent);
167
+ if (!span.endTime) {
168
+ traceData.activeSpans.add(span.id);
169
+ }
119
170
  }
120
171
  initTrace(span) {
172
+ if (this.traceMap.has(span.traceId)) {
173
+ this.logger.debug("Langfuse exporter: Reusing existing trace from local map", {
174
+ traceId: span.traceId,
175
+ spanId: span.id,
176
+ spanName: span.name
177
+ });
178
+ return;
179
+ }
121
180
  const trace = this.client.trace(this.buildTracePayload(span));
122
- this.traceMap.set(span.traceId, { trace, spans: /* @__PURE__ */ new Map(), events: /* @__PURE__ */ new Map() });
181
+ const langfuseData = span.metadata?.langfuse;
182
+ const spanMetadata = /* @__PURE__ */ new Map();
183
+ spanMetadata.set(span.id, {
184
+ parentSpanId: void 0,
185
+ langfusePrompt: langfuseData?.prompt
186
+ });
187
+ this.traceMap.set(span.traceId, {
188
+ trace,
189
+ spans: /* @__PURE__ */ new Map(),
190
+ spanMetadata,
191
+ events: /* @__PURE__ */ new Map(),
192
+ activeSpans: /* @__PURE__ */ new Set(),
193
+ rootSpanId: span.id
194
+ });
123
195
  }
124
196
  getTraceData(options) {
125
197
  const { span, method } = options;
@@ -132,13 +204,13 @@ var LangfuseExporter = class {
132
204
  spanName: span.name,
133
205
  spanType: span.type,
134
206
  isRootSpan: span.isRootSpan,
135
- parentSpanId: span.parent?.id,
207
+ parentSpanId: span.parentSpanId,
136
208
  method
137
209
  });
138
210
  }
139
211
  getLangfuseParent(options) {
140
212
  const { traceData, span, method } = options;
141
- const parentId = span.parent?.id;
213
+ const parentId = span.parentSpanId;
142
214
  if (!parentId) {
143
215
  return traceData.trace;
144
216
  }
@@ -154,7 +226,7 @@ var LangfuseExporter = class {
154
226
  spanName: span.name,
155
227
  spanType: span.type,
156
228
  isRootSpan: span.isRootSpan,
157
- parentSpanId: span.parent?.id,
229
+ parentSpanId: span.parentSpanId,
158
230
  method
159
231
  });
160
232
  }
@@ -167,6 +239,7 @@ var LangfuseExporter = class {
167
239
  if (userId) payload.userId = userId;
168
240
  if (sessionId) payload.sessionId = sessionId;
169
241
  if (span.input) payload.input = span.input;
242
+ if (span.tags?.length) payload.tags = span.tags;
170
243
  payload.metadata = {
171
244
  spanType: span.type,
172
245
  ...span.attributes,
@@ -174,7 +247,23 @@ var LangfuseExporter = class {
174
247
  };
175
248
  return payload;
176
249
  }
177
- buildSpanPayload(span, isCreate) {
250
+ /**
251
+ * Look up the Langfuse prompt from the closest parent span that has one.
252
+ * This enables prompt inheritance for MODEL_GENERATION spans when the prompt
253
+ * is set on a parent span (e.g., AGENT_RUN) rather than directly on the generation.
254
+ */
255
+ findParentLangfusePrompt(traceData, span) {
256
+ let currentSpanId = span.parentSpanId;
257
+ while (currentSpanId) {
258
+ const parentMetadata = traceData.spanMetadata.get(currentSpanId);
259
+ if (parentMetadata?.langfusePrompt) {
260
+ return parentMetadata.langfusePrompt;
261
+ }
262
+ currentSpanId = parentMetadata?.parentSpanId;
263
+ }
264
+ return void 0;
265
+ }
266
+ buildSpanPayload(span, isCreate, traceData) {
178
267
  const payload = {};
179
268
  if (isCreate) {
180
269
  payload.id = span.id;
@@ -185,26 +274,51 @@ var LangfuseExporter = class {
185
274
  if (span.output !== void 0) payload.output = span.output;
186
275
  if (span.endTime !== void 0) payload.endTime = span.endTime;
187
276
  const attributes = span.attributes ?? {};
277
+ const resolvedTraceData = traceData ?? this.traceMap.get(span.traceId);
278
+ let inheritedLangfusePrompt;
279
+ if (span.type === observability$1.SpanType.MODEL_GENERATION && !span.metadata?.langfuse && resolvedTraceData) {
280
+ inheritedLangfusePrompt = this.findParentLangfusePrompt(resolvedTraceData, span);
281
+ }
282
+ const metadata = {
283
+ ...span.metadata,
284
+ ...inheritedLangfusePrompt ? { langfuse: { prompt: inheritedLangfusePrompt } } : {}
285
+ };
188
286
  const attributesToOmit = [];
189
- if (span.type === aiTracing.AISpanType.LLM_GENERATION) {
190
- const llmAttr = attributes;
191
- if (llmAttr.model !== void 0) {
192
- payload.model = llmAttr.model;
287
+ const metadataToOmit = [];
288
+ if (span.type === observability$1.SpanType.MODEL_GENERATION) {
289
+ const modelAttr = attributes;
290
+ if (modelAttr.model !== void 0) {
291
+ payload.model = modelAttr.model;
193
292
  attributesToOmit.push("model");
194
293
  }
195
- if (llmAttr.usage !== void 0) {
196
- payload.usage = llmAttr.usage;
294
+ if (modelAttr.usage !== void 0) {
295
+ payload.usageDetails = formatUsageMetrics(modelAttr.usage);
197
296
  attributesToOmit.push("usage");
198
297
  }
199
- if (llmAttr.parameters !== void 0) {
200
- payload.modelParameters = llmAttr.parameters;
298
+ if (modelAttr.parameters !== void 0) {
299
+ payload.modelParameters = modelAttr.parameters;
201
300
  attributesToOmit.push("parameters");
202
301
  }
302
+ const langfuseData = metadata.langfuse;
303
+ const promptData = langfuseData?.prompt;
304
+ const hasNameAndVersion = promptData?.name !== void 0 && promptData?.version !== void 0;
305
+ const hasId = promptData?.id !== void 0;
306
+ if (hasNameAndVersion || hasId) {
307
+ payload.prompt = {};
308
+ if (promptData?.name !== void 0) payload.prompt.name = promptData.name;
309
+ if (promptData?.version !== void 0) payload.prompt.version = promptData.version;
310
+ if (promptData?.id !== void 0) payload.prompt.id = promptData.id;
311
+ metadataToOmit.push("langfuse");
312
+ }
313
+ if (modelAttr.completionStartTime !== void 0) {
314
+ payload.completionStartTime = modelAttr.completionStartTime;
315
+ attributesToOmit.push("completionStartTime");
316
+ }
203
317
  }
204
318
  payload.metadata = {
205
319
  spanType: span.type,
206
- ...aiTracing.omitKeys(attributes, attributesToOmit),
207
- ...span.metadata
320
+ ...utils.omitKeys(attributes, attributesToOmit),
321
+ ...utils.omitKeys(metadata, metadataToOmit)
208
322
  };
209
323
  if (span.errorInfo) {
210
324
  payload.level = "ERROR";
@@ -212,14 +326,64 @@ var LangfuseExporter = class {
212
326
  }
213
327
  return payload;
214
328
  }
329
+ async addScoreToTrace({
330
+ traceId,
331
+ spanId,
332
+ score,
333
+ reason,
334
+ scorerName,
335
+ metadata
336
+ }) {
337
+ if (!this.client) return;
338
+ try {
339
+ await this.client.score({
340
+ id: `${traceId}-${scorerName}`,
341
+ traceId,
342
+ observationId: spanId,
343
+ name: scorerName,
344
+ value: score,
345
+ ...metadata?.sessionId ? { sessionId: metadata.sessionId } : {},
346
+ metadata: { ...reason ? { reason } : {} },
347
+ dataType: "NUMERIC"
348
+ });
349
+ } catch (error) {
350
+ this.logger.error("Langfuse exporter: Error adding score to trace", {
351
+ error,
352
+ traceId,
353
+ spanId,
354
+ scorerName
355
+ });
356
+ }
357
+ }
215
358
  async shutdown() {
216
359
  if (this.client) {
217
360
  await this.client.shutdownAsync();
218
361
  }
219
362
  this.traceMap.clear();
363
+ await super.shutdown();
220
364
  }
221
365
  };
222
366
 
367
+ // src/helpers.ts
368
+ function withLangfusePrompt(prompt) {
369
+ return (opts) => ({
370
+ ...opts,
371
+ metadata: {
372
+ ...opts.metadata,
373
+ langfuse: {
374
+ ...opts.metadata?.langfuse,
375
+ prompt: {
376
+ ...prompt.name !== void 0 && { name: prompt.name },
377
+ ...prompt.version !== void 0 && { version: prompt.version },
378
+ ...prompt.id !== void 0 && { id: prompt.id }
379
+ }
380
+ }
381
+ }
382
+ });
383
+ }
384
+
223
385
  exports.LangfuseExporter = LangfuseExporter;
386
+ exports.formatUsageMetrics = formatUsageMetrics;
387
+ exports.withLangfusePrompt = withLangfusePrompt;
224
388
  //# sourceMappingURL=index.cjs.map
225
389
  //# sourceMappingURL=index.cjs.map