@mastra/langsmith 0.0.0-error-handler-fix-20251020202607 → 0.0.0-execa-dynamic-import-20260304221256

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/LICENSE.md CHANGED
@@ -1,3 +1,18 @@
1
+ Portions of this software are licensed as follows:
2
+
3
+ - All content that resides under any directory named "ee/" within this
4
+ repository, including but not limited to:
5
+ - `packages/core/src/auth/ee/`
6
+ - `packages/server/src/server/auth/ee/`
7
+ is licensed under the license defined in `ee/LICENSE`.
8
+
9
+ - All third-party components incorporated into the Mastra Software are
10
+ licensed under the original license provided by the owner of the
11
+ applicable component.
12
+
13
+ - Content outside of the above-mentioned directories or restrictions is
14
+ available under the "Apache License 2.0" as defined below.
15
+
1
16
  # Apache License 2.0
2
17
 
3
18
  Copyright (c) 2025 Kepler Software, Inc.
package/README.md CHANGED
@@ -10,21 +10,51 @@ npm install @mastra/langsmith
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
+ LANGSMITH_API_KEY=lsv2_pt_...
20
+
21
+ # Optional
22
+ LANGCHAIN_PROJECT=my-project # Project name, defaults to "default"
23
+ ```
24
+
13
25
  ```typescript
14
26
  import { LangSmithExporter } from '@mastra/langsmith';
15
27
 
16
- // Set process.env.LANGSMITH_TRACING = "true";
28
+ const mastra = new Mastra({
29
+ ...,
30
+ observability: {
31
+ configs: {
32
+ langsmith: {
33
+ serviceName: 'my-service',
34
+ exporters: [new LangSmithExporter()],
35
+ },
36
+ },
37
+ },
38
+ });
39
+ ```
40
+
41
+ ### Explicit Configuration
42
+
43
+ You can also pass credentials directly:
44
+
45
+ ```typescript
46
+ import { LangSmithExporter } from '@mastra/langsmith';
17
47
 
18
- // Use with Mastra
19
48
  const mastra = new Mastra({
20
49
  ...,
21
50
  observability: {
22
51
  configs: {
23
52
  langsmith: {
24
- serviceName: 'service',
53
+ serviceName: 'my-service',
25
54
  exporters: [
26
55
  new LangSmithExporter({
27
- apiKey: process.env.LANGSMITH_API_KEY, // Defaults to process.env.LANGSMITH_API_KEY
56
+ apiKey: 'lsv2_pt_...',
57
+ projectName: 'my-custom-project', // Optional
28
58
  }),
29
59
  ],
30
60
  },
@@ -33,9 +63,18 @@ const mastra = new Mastra({
33
63
  });
34
64
  ```
35
65
 
66
+ ### Configuration Options
67
+
68
+ | Option | Type | Description |
69
+ | ------------- | -------- | ------------------------------------------------------------------------------------------ |
70
+ | `apiKey` | `string` | LangSmith API key. Defaults to `LANGSMITH_API_KEY` env var |
71
+ | `projectName` | `string` | The name of the LangSmith project to send traces to. Overrides `LANGCHAIN_PROJECT` env var |
72
+ | `apiUrl` | `string` | Custom LangSmith API URL (for self-hosted instances) |
73
+ | `client` | `Client` | Custom LangSmith client instance |
74
+
36
75
  ## Features
37
76
 
38
- ### AI Tracing
77
+ ### Tracing
39
78
 
40
79
  - **Automatic span mapping**: Root spans become LangSmith traces
41
80
  - **Type-specific metadata**: Extracts relevant metadata for each span type (agents, tools, workflows)
@@ -0,0 +1,83 @@
1
+ /**
2
+ * LangSmith Tracing Options Helpers
3
+ *
4
+ * These helpers integrate with the `buildTracingOptions` pattern from
5
+ * `@mastra/observability` to add LangSmith-specific tracing features.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { buildTracingOptions } from '@mastra/observability';
10
+ * import { withLangsmithMetadata } from '@mastra/langsmith';
11
+ *
12
+ * const agent = new Agent({
13
+ * defaultGenerateOptions: {
14
+ * tracingOptions: buildTracingOptions(
15
+ * withLangsmithMetadata({ projectName: 'my-project' })
16
+ * ),
17
+ * },
18
+ * });
19
+ * ```
20
+ */
21
+ import type { TracingOptionsUpdater } from '@mastra/observability';
22
+ /**
23
+ * LangSmith vendor metadata that can be passed via span metadata.
24
+ * These fields are extracted by the LangSmith exporter and used
25
+ * to override default configuration on a per-span basis.
26
+ */
27
+ export interface LangSmithMetadataInput {
28
+ /**
29
+ * Override the project name for this span and its children.
30
+ * This allows dynamically routing traces to different LangSmith projects.
31
+ */
32
+ projectName?: string;
33
+ /**
34
+ * Session ID for grouping related traces in LangSmith.
35
+ */
36
+ sessionId?: string;
37
+ /**
38
+ * Session name for display in LangSmith.
39
+ */
40
+ sessionName?: string;
41
+ }
42
+ /**
43
+ * Adds LangSmith metadata to the tracing options.
44
+ *
45
+ * The metadata is added under `metadata.langsmith` and allows you to:
46
+ * - Route traces to different LangSmith projects via `projectName`
47
+ * - Group traces by session via `sessionId` and `sessionName`
48
+ *
49
+ * @param metadata - The LangSmith metadata to add
50
+ * @returns A TracingOptionsUpdater function for use with `buildTracingOptions`
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * import { buildTracingOptions } from '@mastra/observability';
55
+ * import { withLangsmithMetadata } from '@mastra/langsmith';
56
+ *
57
+ * // Route traces to a specific project
58
+ * const tracingOptions = buildTracingOptions(
59
+ * withLangsmithMetadata({ projectName: 'customer-support' }),
60
+ * );
61
+ *
62
+ * // Or set multiple fields
63
+ * const tracingOptions = buildTracingOptions(
64
+ * withLangsmithMetadata({
65
+ * projectName: 'my-project',
66
+ * sessionId: 'session-123',
67
+ * }),
68
+ * );
69
+ *
70
+ * // Use in agent config
71
+ * const agent = new Agent({
72
+ * name: 'support-agent',
73
+ * model: openai('gpt-4o'),
74
+ * defaultGenerateOptions: {
75
+ * tracingOptions: buildTracingOptions(
76
+ * withLangsmithMetadata({ projectName: 'support-traces' })
77
+ * ),
78
+ * },
79
+ * });
80
+ * ```
81
+ */
82
+ export declare function withLangsmithMetadata(metadata: LangSmithMetadataInput): TracingOptionsUpdater;
83
+ //# 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;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,sBAAsB,GAAG,qBAAqB,CAW7F"}
package/dist/index.cjs CHANGED
@@ -1,59 +1,65 @@
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 langsmith = require('langsmith');
6
7
 
7
- // src/ai-tracing.ts
8
+ // src/tracing.ts
8
9
 
9
10
  // src/metrics.ts
10
- function normalizeUsageMetrics(llmAttr) {
11
+ function formatUsageMetrics(usage) {
11
12
  const metrics = {};
12
- if (llmAttr.usage?.inputTokens !== void 0) {
13
- metrics.input_tokens = llmAttr.usage?.inputTokens;
14
- } else if (llmAttr.usage?.promptTokens !== void 0) {
15
- metrics.input_tokens = llmAttr.usage?.promptTokens;
13
+ if (usage?.inputTokens !== void 0) {
14
+ metrics.input_tokens = usage.inputTokens;
16
15
  }
17
- if (llmAttr.usage?.outputTokens !== void 0) {
18
- metrics.output_tokens = llmAttr.usage?.outputTokens;
19
- } else if (llmAttr.usage?.completionTokens !== void 0) {
20
- metrics.output_tokens = llmAttr.usage?.completionTokens;
16
+ if (usage?.outputTokens !== void 0) {
17
+ metrics.output_tokens = usage.outputTokens;
21
18
  }
22
- if (llmAttr.usage?.totalTokens !== void 0) {
23
- metrics.total_tokens = llmAttr.usage?.totalTokens;
24
- } else if (typeof llmAttr.usage?.inputTokens === "number" && typeof llmAttr.usage?.outputTokens === "number") {
25
- metrics.total_tokens = llmAttr.usage?.inputTokens + llmAttr.usage?.outputTokens;
19
+ if (metrics.input_tokens !== void 0 && metrics.output_tokens !== void 0) {
20
+ metrics.total_tokens = metrics.input_tokens + metrics.output_tokens;
26
21
  }
27
- if (llmAttr.usage?.reasoningTokens !== void 0) {
22
+ if (usage?.outputDetails?.reasoning !== void 0) {
28
23
  metrics.output_token_details = {
29
24
  ...metrics.output_token_details ?? {},
30
- reasoning_tokens: llmAttr.usage?.reasoningTokens
25
+ reasoning_tokens: usage.outputDetails.reasoning
31
26
  };
32
27
  }
33
- if (llmAttr.usage?.promptCacheHitTokens !== void 0) {
28
+ if (usage?.inputDetails?.cacheRead !== void 0) {
34
29
  metrics.input_token_details = {
35
30
  ...metrics.input_token_details ?? {},
36
- cache_read: llmAttr.usage?.promptCacheHitTokens
31
+ cache_read: usage.inputDetails.cacheRead
37
32
  };
38
33
  }
39
- if (llmAttr.usage?.promptCacheMissTokens !== void 0) {
34
+ if (usage?.inputDetails?.cacheWrite !== void 0) {
40
35
  metrics.input_token_details = {
41
36
  ...metrics.input_token_details ?? {},
42
- cache_write: llmAttr.usage?.promptCacheMissTokens
37
+ cache_write: usage.inputDetails.cacheWrite
38
+ };
39
+ }
40
+ if (usage?.inputDetails?.audio !== void 0) {
41
+ metrics.input_token_details = {
42
+ ...metrics.input_token_details ?? {},
43
+ audio: usage.inputDetails.audio
44
+ };
45
+ }
46
+ if (usage?.outputDetails?.audio !== void 0) {
47
+ metrics.output_token_details = {
48
+ ...metrics.output_token_details ?? {},
49
+ audio: usage.outputDetails.audio
43
50
  };
44
51
  }
45
52
  return metrics;
46
53
  }
47
54
 
48
- // src/ai-tracing.ts
55
+ // src/tracing.ts
49
56
  var DEFAULT_SPAN_TYPE = "chain";
50
57
  var SPAN_TYPE_EXCEPTIONS = {
51
- [aiTracing.AISpanType.LLM_GENERATION]: "llm",
52
- [aiTracing.AISpanType.LLM_CHUNK]: "llm",
53
- [aiTracing.AISpanType.TOOL_CALL]: "tool",
54
- [aiTracing.AISpanType.MCP_TOOL_CALL]: "tool",
55
- [aiTracing.AISpanType.WORKFLOW_CONDITIONAL_EVAL]: "chain",
56
- [aiTracing.AISpanType.WORKFLOW_WAIT_EVENT]: "chain"
58
+ [observability$1.SpanType.MODEL_GENERATION]: "llm",
59
+ [observability$1.SpanType.TOOL_CALL]: "tool",
60
+ [observability$1.SpanType.MCP_TOOL_CALL]: "tool",
61
+ [observability$1.SpanType.WORKFLOW_CONDITIONAL_EVAL]: "chain",
62
+ [observability$1.SpanType.WORKFLOW_WAIT_EVENT]: "chain"
57
63
  };
58
64
  function mapSpanType(spanType) {
59
65
  return SPAN_TYPE_EXCEPTIONS[spanType] ?? DEFAULT_SPAN_TYPE;
@@ -61,203 +67,164 @@ function mapSpanType(spanType) {
61
67
  function isKVMap(value) {
62
68
  return value != null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date);
63
69
  }
64
- var LangSmithExporter = class {
70
+ var LangSmithExporter = class extends observability.TrackingExporter {
65
71
  name = "langsmith";
66
- traceMap = /* @__PURE__ */ new Map();
67
- logger;
68
- config;
69
- client;
70
- constructor(config) {
71
- this.logger = new logger.ConsoleLogger({ level: config.logLevel ?? "warn" });
72
- config.apiKey = config.apiKey ?? process.env.LANGSMITH_API_KEY;
73
- if (!config.apiKey) {
74
- this.logger.error("LangSmithExporter: Missing required credentials, exporter will be disabled", {
75
- hasApiKey: !!config.apiKey
76
- });
77
- this.config = null;
78
- this.client = null;
79
- return;
80
- }
81
- this.client = config.client ?? new langsmith.Client(config);
82
- this.config = config;
83
- }
84
- async exportEvent(event) {
85
- if (!this.config) {
86
- return;
87
- }
88
- if (event.exportedSpan.isEvent) {
89
- await this.handleEventSpan(event.exportedSpan);
72
+ #client;
73
+ constructor(config = {}) {
74
+ const apiKey = config.apiKey ?? process.env.LANGSMITH_API_KEY;
75
+ super({
76
+ ...config,
77
+ apiKey
78
+ });
79
+ if (!apiKey) {
80
+ this.setDisabled(`Missing required credentials (apiKey: ${!!apiKey})`);
90
81
  return;
91
82
  }
92
- switch (event.type) {
93
- case "span_started":
94
- await this.handleSpanStarted(event.exportedSpan);
95
- break;
96
- case "span_updated":
97
- await this.handleSpanUpdateOrEnd(event.exportedSpan, false);
98
- break;
99
- case "span_ended":
100
- await this.handleSpanUpdateOrEnd(event.exportedSpan, true);
101
- break;
102
- }
83
+ this.#client = config.client ?? new langsmith.Client(this.config);
103
84
  }
104
- initializeRootSpan(span) {
105
- this.traceMap.set(span.traceId, { spans: /* @__PURE__ */ new Map(), activeIds: /* @__PURE__ */ new Set() });
85
+ skipBuildRootTask = true;
86
+ async _buildRoot(_args) {
87
+ throw new Error("Method not implemented.");
106
88
  }
107
- async handleSpanStarted(span) {
108
- this.logger.debug("LangSmith exporter: handleSpanStarted", span.id, span.name);
109
- if (span.isRootSpan) {
110
- this.initializeRootSpan(span);
111
- }
112
- const method = "handleSpanStarted";
113
- const spanData = this.getSpanData({ span, method });
114
- if (!spanData) {
89
+ async _buildSpan(args) {
90
+ const { span, traceData } = args;
91
+ const parent = span.isRootSpan ? void 0 : traceData.getParent(args);
92
+ if (!span.isRootSpan && !parent) {
115
93
  return;
116
94
  }
117
- if (!span.isEvent) {
118
- spanData.activeIds.add(span.id);
119
- }
120
95
  const payload = {
121
96
  name: span.name,
122
- run_type: mapSpanType(span.type),
123
- ...this.buildRunTreePayload(span)
97
+ ...this.buildRunTreePayload(span, traceData, true)
124
98
  };
125
- const langsmithParent = this.getLangSmithParent({ spanData, span, method });
126
- let langsmithRunTree;
127
- if (!langsmithParent) {
128
- langsmithRunTree = new langsmith.RunTree(payload);
129
- } else {
130
- langsmithRunTree = langsmithParent.createChild(payload);
131
- }
132
- spanData.spans.set(span.id, langsmithRunTree);
133
- await langsmithRunTree.postRun();
99
+ const langSmithSpan = span.isRootSpan ? new langsmith.RunTree(payload) : parent.createChild(payload);
100
+ await langSmithSpan.postRun();
101
+ return langSmithSpan;
134
102
  }
135
- async handleSpanUpdateOrEnd(span, isEnd) {
136
- this.logger.debug("LangSmith exporter: handleSpanUpdateOrEnd", span.id, span.name, "isEnd:", isEnd);
137
- const method = isEnd ? "handleSpanEnd" : "handleSpanUpdate";
138
- const spanData = this.getSpanData({ span, method });
139
- if (!spanData) {
103
+ async _buildEvent(args) {
104
+ const langSmithSpan = await this._buildSpan(args);
105
+ if (!langSmithSpan) {
140
106
  return;
141
107
  }
142
- const langsmithRunTree = spanData.spans.get(span.id);
143
- if (!langsmithRunTree) {
144
- this.logger.warn("LangSmith exporter: No LangSmith span found for span update/end", {
145
- traceId: span.traceId,
146
- spanId: span.id,
147
- spanName: span.name,
148
- spanType: span.type,
149
- isRootSpan: span.isRootSpan,
150
- parentSpanId: span.parentSpanId,
151
- method
152
- });
108
+ await langSmithSpan.end({ endTime: args.span.startTime.getTime() });
109
+ await langSmithSpan.patchRun();
110
+ return langSmithSpan;
111
+ }
112
+ async _updateSpan(args) {
113
+ await this.handleSpanUpdateOrEnd({ ...args, isEnd: false });
114
+ }
115
+ async _finishSpan(args) {
116
+ await this.handleSpanUpdateOrEnd({ ...args, isEnd: true });
117
+ }
118
+ async _abortSpan(args) {
119
+ const { span, reason } = args;
120
+ span.error = reason.message;
121
+ span.metadata = {
122
+ ...span.metadata,
123
+ errorDetails: reason
124
+ };
125
+ await span.end();
126
+ await span.patchRun();
127
+ }
128
+ async handleSpanUpdateOrEnd(args) {
129
+ const { span, traceData, isEnd } = args;
130
+ const langSmithSpan = traceData.getSpan({ spanId: span.id });
131
+ if (!langSmithSpan) {
153
132
  return;
154
133
  }
155
- const updatePayload = this.buildRunTreePayload(span);
156
- langsmithRunTree.metadata = {
157
- ...langsmithRunTree.metadata,
134
+ const updatePayload = this.buildRunTreePayload(span, traceData);
135
+ langSmithSpan.metadata = {
136
+ ...langSmithSpan.metadata,
158
137
  ...updatePayload.metadata
159
138
  };
160
139
  if (updatePayload.inputs != null) {
161
- langsmithRunTree.inputs = updatePayload.inputs;
140
+ langSmithSpan.inputs = updatePayload.inputs;
162
141
  }
163
142
  if (updatePayload.outputs != null) {
164
- langsmithRunTree.outputs = updatePayload.outputs;
143
+ langSmithSpan.outputs = updatePayload.outputs;
165
144
  }
166
145
  if (updatePayload.error != null) {
167
- langsmithRunTree.error = updatePayload.error;
146
+ langSmithSpan.error = updatePayload.error;
147
+ }
148
+ if (span.type === observability$1.SpanType.MODEL_GENERATION) {
149
+ const modelAttr = span.attributes ?? {};
150
+ if (modelAttr.completionStartTime !== void 0) {
151
+ langSmithSpan.addEvent({
152
+ name: "new_token",
153
+ time: modelAttr.completionStartTime.toISOString()
154
+ });
155
+ }
168
156
  }
169
157
  if (isEnd) {
170
158
  if (span.endTime) {
171
- await langsmithRunTree.end({ endTime: span.endTime.getTime() / 1e3 });
159
+ await langSmithSpan.end({ endTime: span.endTime.getTime() });
172
160
  } else {
173
- await langsmithRunTree.end();
174
- }
175
- await langsmithRunTree.patchRun();
176
- if (!span.isEvent) {
177
- spanData.activeIds.delete(span.id);
178
- }
179
- if (spanData.activeIds.size === 0) {
180
- this.traceMap.delete(span.traceId);
161
+ await langSmithSpan.end();
181
162
  }
182
163
  }
164
+ await langSmithSpan.patchRun();
183
165
  }
184
- async handleEventSpan(span) {
185
- if (span.isRootSpan) {
186
- this.logger.debug("LangSmith exporter: Creating logger for event", {
187
- traceId: span.traceId,
188
- spanId: span.id,
189
- spanName: span.name,
190
- method: "handleEventSpan"
191
- });
192
- this.initializeRootSpan(span);
193
- }
194
- const method = "handleEventSpan";
195
- const spanData = this.getSpanData({ span, method });
196
- if (!spanData) {
197
- return;
198
- }
199
- const langsmithParent = this.getLangSmithParent({ spanData, span, method });
200
- const payload = {
201
- ...this.buildRunTreePayload(span),
202
- name: span.name,
203
- type: mapSpanType(span.type),
204
- startTime: span.startTime.getTime() / 1e3
205
- };
206
- let langsmithRunTree;
207
- if (!langsmithParent) {
208
- langsmithRunTree = new langsmith.RunTree(payload);
209
- } else {
210
- langsmithRunTree = langsmithParent.createChild(payload);
211
- }
212
- await langsmithRunTree.postRun();
213
- await langsmithRunTree.end({ endTime: span.startTime.getTime() / 1e3 });
214
- await langsmithRunTree.patchRun();
215
- }
216
- getSpanData(options) {
217
- const { span, method } = options;
218
- if (this.traceMap.has(span.traceId)) {
219
- return this.traceMap.get(span.traceId);
166
+ /**
167
+ * Find LangSmith vendor metadata by walking up the span hierarchy and merging.
168
+ * Metadata is merged from ancestors with child values taking precedence over parent values.
169
+ *
170
+ * TODO(2.0): Extract shared `findVendorMetadata()` to base TrackingExporter class
171
+ * and reuse here and in LangfuseExporter.findLangfusePrompt()
172
+ */
173
+ findLangsmithMetadata(traceData, span) {
174
+ const metadataChain = [];
175
+ let currentSpanId = span.id;
176
+ while (currentSpanId) {
177
+ const providerMetadata = traceData.getMetadata({ spanId: currentSpanId });
178
+ if (providerMetadata) {
179
+ metadataChain.push(providerMetadata);
180
+ }
181
+ currentSpanId = traceData.getParentId({ spanId: currentSpanId });
220
182
  }
221
- this.logger.warn("LangSmith exporter: No span data found for span", {
222
- traceId: span.traceId,
223
- spanId: span.id,
224
- spanName: span.name,
225
- spanType: span.type,
226
- isRootSpan: span.isRootSpan,
227
- parentSpanId: span.parentSpanId,
228
- method
229
- });
230
- }
231
- getLangSmithParent(options) {
232
- const { spanData, span, method } = options;
233
- const parentId = span.parentSpanId;
234
- if (!parentId) {
183
+ if (metadataChain.length === 0) {
235
184
  return void 0;
236
185
  }
237
- if (spanData.spans.has(parentId)) {
238
- return spanData.spans.get(parentId);
186
+ const merged = {};
187
+ for (let i = metadataChain.length - 1; i >= 0; i--) {
188
+ const meta = metadataChain[i];
189
+ if (meta.projectName !== void 0) merged.projectName = meta.projectName;
190
+ if (meta.sessionId !== void 0) merged.sessionId = meta.sessionId;
191
+ if (meta.sessionName !== void 0) merged.sessionName = meta.sessionName;
239
192
  }
240
- if (parentId && !spanData.spans.has(parentId)) {
241
- return void 0;
242
- }
243
- this.logger.warn("LangSmith exporter: No parent data found for span", {
193
+ this.logger.debug(`${this.name}: merged vendor metadata from hierarchy`, {
244
194
  traceId: span.traceId,
245
195
  spanId: span.id,
246
- spanName: span.name,
247
- spanType: span.type,
248
- isRootSpan: span.isRootSpan,
249
- parentSpanId: span.parentSpanId,
250
- method
196
+ metadataKeys: Object.keys(merged),
197
+ ancestorCount: metadataChain.length
251
198
  });
199
+ return merged;
252
200
  }
253
- buildRunTreePayload(span) {
201
+ buildRunTreePayload(span, traceData, isNew = false) {
202
+ const vendorMetadata = this.findLangsmithMetadata(traceData, span);
203
+ const spanMetadata = span.metadata ? utils.omitKeys(span.metadata, ["langsmith"]) : {};
254
204
  const payload = {
255
- client: this.client,
205
+ client: this.#client,
256
206
  metadata: {
257
207
  mastra_span_type: span.type,
258
- ...span.metadata
208
+ ...spanMetadata
259
209
  }
260
210
  };
211
+ if (isNew) {
212
+ payload.run_type = mapSpanType(span.type);
213
+ payload.start_time = span.startTime.getTime();
214
+ }
215
+ const projectName = vendorMetadata?.projectName ?? this.config.projectName;
216
+ if (projectName) {
217
+ payload.project_name = projectName;
218
+ }
219
+ if (vendorMetadata?.sessionId) {
220
+ payload.metadata.session_id = vendorMetadata.sessionId;
221
+ }
222
+ if (vendorMetadata?.sessionName) {
223
+ payload.metadata.session_name = vendorMetadata.sessionName;
224
+ }
225
+ if (span.isRootSpan && span.tags?.length) {
226
+ payload.tags = span.tags;
227
+ }
261
228
  if (span.input !== void 0) {
262
229
  payload.inputs = isKVMap(span.input) ? span.input : { input: span.input };
263
230
  }
@@ -265,19 +232,19 @@ var LangSmithExporter = class {
265
232
  payload.outputs = isKVMap(span.output) ? span.output : { output: span.output };
266
233
  }
267
234
  const attributes = span.attributes ?? {};
268
- if (span.type === aiTracing.AISpanType.LLM_GENERATION) {
269
- const llmAttr = attributes;
270
- if (llmAttr.model !== void 0) {
271
- payload.metadata.ls_model_name = llmAttr.model;
235
+ if (span.type === observability$1.SpanType.MODEL_GENERATION) {
236
+ const modelAttr = attributes;
237
+ if (modelAttr.model !== void 0) {
238
+ payload.metadata.ls_model_name = modelAttr.model;
272
239
  }
273
- if (llmAttr.provider !== void 0) {
274
- payload.metadata.ls_provider = llmAttr.provider;
240
+ if (modelAttr.provider !== void 0) {
241
+ payload.metadata.ls_provider = modelAttr.provider;
275
242
  }
276
- payload.metadata.usage_metadata = normalizeUsageMetrics(llmAttr);
277
- if (llmAttr.parameters !== void 0) {
278
- payload.metadata.modelParameters = llmAttr.parameters;
243
+ payload.metadata.usage_metadata = formatUsageMetrics(modelAttr.usage);
244
+ if (modelAttr.parameters !== void 0) {
245
+ payload.metadata.modelParameters = modelAttr.parameters;
279
246
  }
280
- const otherAttributes = aiTracing.omitKeys(attributes, ["model", "usage", "parameters"]);
247
+ const otherAttributes = utils.omitKeys(attributes, ["model", "provider", "usage", "parameters", "completionStartTime"]);
281
248
  payload.metadata = {
282
249
  ...payload.metadata,
283
250
  ...otherAttributes
@@ -294,20 +261,23 @@ var LangSmithExporter = class {
294
261
  }
295
262
  return payload;
296
263
  }
297
- async shutdown() {
298
- if (!this.config) {
299
- return;
300
- }
301
- for (const [_traceId, spanData] of this.traceMap) {
302
- for (const [_spanId, runTree] of spanData.spans) {
303
- await runTree.end();
304
- await runTree.patchRun();
264
+ };
265
+
266
+ // src/helpers.ts
267
+ function withLangsmithMetadata(metadata) {
268
+ return (opts) => ({
269
+ ...opts,
270
+ metadata: {
271
+ ...opts.metadata,
272
+ langsmith: {
273
+ ...opts.metadata?.langsmith,
274
+ ...metadata
305
275
  }
306
276
  }
307
- this.traceMap.clear();
308
- }
309
- };
277
+ });
278
+ }
310
279
 
311
280
  exports.LangSmithExporter = LangSmithExporter;
281
+ exports.withLangsmithMetadata = withLangsmithMetadata;
312
282
  //# sourceMappingURL=index.cjs.map
313
283
  //# sourceMappingURL=index.cjs.map