{"version":3,"sources":["../src/formatter.ts","../src/metrics.ts","../src/thread-reconstruction.ts","../src/tracing.ts"],"names":["SpanType","TrackingExporter","initLogger","currentSpan","omitKeys"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Message format conversion utilities for Braintrust.\n *\n * Converts AI SDK message format (v4/v5) to OpenAI Chat Completion format,\n * which Braintrust requires for proper rendering of threads.\n */\n\n// ==============================================================================\n// Utility functions\n// ==============================================================================\n\n/**\n * Remove null and undefined values from an object (shallow)\n */\nexport function removeNullish<T extends Record<string, unknown>>(obj: T): Partial<T> {\n  return Object.fromEntries(Object.entries(obj).filter(([_, v]) => v != null)) as Partial<T>;\n}\n\n// ==============================================================================\n// Type definitions for AI SDK message format conversion to OpenAI format\n// ==============================================================================\n\n/**\n * AI SDK content part types (both v4 and v5)\n */\ninterface AISDKTextPart {\n  type: 'text';\n  text: string;\n}\n\ninterface AISDKImagePart {\n  type: 'image';\n  image?: string | Uint8Array | URL;\n  mimeType?: string;\n}\n\ninterface AISDKFilePart {\n  type: 'file';\n  data?: string | Uint8Array | URL;\n  filename?: string;\n  name?: string;\n  mimeType?: string;\n}\n\ninterface AISDKReasoningPart {\n  type: 'reasoning';\n  text?: string;\n}\n\ninterface AISDKToolCallPart {\n  type: 'tool-call';\n  toolCallId: string;\n  toolName: string;\n  args?: unknown; // AI SDK v4\n  input?: unknown; // AI SDK v5\n}\n\ninterface AISDKToolResultPart {\n  type: 'tool-result';\n  toolCallId: string;\n  result?: unknown; // AI SDK v4\n  output?: unknown; // AI SDK v5\n}\n\ntype AISDKContentPart =\n  | AISDKTextPart\n  | AISDKImagePart\n  | AISDKFilePart\n  | AISDKReasoningPart\n  | AISDKToolCallPart\n  | AISDKToolResultPart\n  | { type: string; [key: string]: unknown }; // Catch-all for unknown types\n\n/**\n * AI SDK message format (input format for conversion)\n */\ninterface AISDKMessage {\n  role: 'user' | 'assistant' | 'system' | 'tool';\n  content: string | AISDKContentPart[];\n  [key: string]: unknown; // Allow additional properties\n}\n\n/**\n * OpenAI Chat Completion tool call format\n */\nexport interface OpenAIToolCall {\n  id: string;\n  type: 'function';\n  function: {\n    name: string;\n    arguments: string;\n  };\n}\n\n/**\n * OpenAI Chat Completion message format (output format)\n */\nexport interface OpenAIMessage {\n  role: 'user' | 'assistant' | 'system' | 'tool';\n  content: string;\n  tool_calls?: OpenAIToolCall[];\n  tool_call_id?: string;\n  [key: string]: unknown; // Allow additional properties\n}\n\n// ==============================================================================\n// Message conversion functions\n// ==============================================================================\n\n/**\n * Converts a content part to a string representation.\n * Handles text, image, file, reasoning, and other content types.\n */\nfunction convertContentPart(part: AISDKContentPart | null | undefined): string | null {\n  if (!part || typeof part !== 'object') {\n    return null;\n  }\n\n  switch (part.type) {\n    case 'text':\n      return (part as AISDKTextPart).text || null;\n\n    case 'image':\n      // Represent image content with a placeholder\n      return '[image]';\n\n    case 'file': {\n      // Represent file content with filename if available\n      const filePart = part as AISDKFilePart;\n      if (filePart.filename || filePart.name) {\n        return `[file: ${filePart.filename || filePart.name}]`;\n      }\n      return '[file]';\n    }\n\n    case 'reasoning': {\n      // Represent reasoning/thinking content\n      const reasoningPart = part as AISDKReasoningPart;\n      if (typeof reasoningPart.text === 'string' && reasoningPart.text.length > 0) {\n        return `[reasoning: ${reasoningPart.text.substring(0, 100)}${reasoningPart.text.length > 100 ? '...' : ''}]`;\n      }\n      return '[reasoning]';\n    }\n\n    case 'tool-call':\n      // Tool calls are handled separately in assistant messages\n      return null;\n\n    case 'tool-result':\n      // Tool results are handled separately in tool messages\n      return null;\n\n    default: {\n      // For unknown types, try to extract any text-like content\n      const unknownPart = part as { type?: string; text?: string; content?: string };\n      if (typeof unknownPart.text === 'string') {\n        return unknownPart.text;\n      }\n      if (typeof unknownPart.content === 'string') {\n        return unknownPart.content;\n      }\n      // Represent unknown content type\n      return `[${unknownPart.type || 'unknown'}]`;\n    }\n  }\n}\n\n/**\n * Serializes tool result data to a string for OpenAI format.\n */\nfunction serializeToolResult(resultData: unknown): string {\n  if (typeof resultData === 'string') {\n    return resultData;\n  }\n  if (resultData && typeof resultData === 'object' && 'value' in resultData) {\n    const valueData = (resultData as { value: unknown }).value;\n    return typeof valueData === 'string' ? valueData : JSON.stringify(valueData);\n  }\n  if (resultData === undefined || resultData === null) {\n    return '';\n  }\n  try {\n    return JSON.stringify(resultData);\n  } catch {\n    return '[unserializable result]';\n  }\n}\n\n/**\n * Converts AI SDK message format to OpenAI Chat Completion format for Braintrust.\n *\n * Supports both AI SDK v4 and v5 formats:\n *   - v4 uses 'args' for tool calls and 'result' for tool results\n *   - v5 uses 'input' for tool calls and 'output' for tool results\n *\n * AI SDK format:\n *   { role: \"user\", content: [{ type: \"text\", text: \"hello\" }] }\n *   { role: \"assistant\", content: [{ type: \"text\", text: \"...\" }, { type: \"tool-call\", toolCallId: \"...\", toolName: \"...\", args: {...} }] }\n *   { role: \"tool\", content: [{ type: \"tool-result\", toolCallId: \"...\", result: {...} }] }\n *\n * OpenAI format (what Braintrust expects):\n *   { role: \"user\", content: \"hello\" }\n *   { role: \"assistant\", content: \"...\", tool_calls: [{ id: \"...\", type: \"function\", function: { name: \"...\", arguments: \"...\" } }] }\n *   { role: \"tool\", content: \"result\", tool_call_id: \"...\" }\n */\nexport function convertAISDKMessage(message: AISDKMessage | OpenAIMessage | unknown): OpenAIMessage | unknown {\n  if (!message || typeof message !== 'object') {\n    return message;\n  }\n\n  const { role, content, ...rest } = message as AISDKMessage;\n\n  // If content is already a string, return as-is (already in OpenAI format)\n  if (typeof content === 'string') {\n    return message;\n  }\n\n  // If content is an array (AI SDK format), convert based on role\n  if (Array.isArray(content)) {\n    // Handle empty content arrays\n    if (content.length === 0) {\n      return { role, content: '', ...rest };\n    }\n\n    // For user/system messages, extract text and represent non-text content\n    if (role === 'user' || role === 'system') {\n      const contentParts = content.map((part: AISDKContentPart) => convertContentPart(part)).filter(Boolean);\n\n      return {\n        role,\n        content: contentParts.length > 0 ? contentParts.join('\\n') : '',\n        ...rest,\n      };\n    }\n\n    // For assistant messages, extract text, non-text content, AND tool calls\n    if (role === 'assistant') {\n      const contentParts = content\n        .filter((part: AISDKContentPart) => part?.type !== 'tool-call')\n        .map((part: AISDKContentPart) => convertContentPart(part))\n        .filter(Boolean);\n\n      const toolCallParts = content.filter((part: AISDKContentPart) => part?.type === 'tool-call');\n\n      const result: OpenAIMessage = {\n        role,\n        content: contentParts.length > 0 ? (contentParts as string[]).join('\\n') : '',\n        ...rest,\n      };\n\n      // Add tool_calls array if there are tool calls\n      if (toolCallParts.length > 0) {\n        result.tool_calls = toolCallParts.map((tc: AISDKContentPart) => {\n          const toolCall = tc as AISDKToolCallPart;\n          const toolCallId = toolCall.toolCallId;\n          const toolName = toolCall.toolName;\n          // Support both v4 'args' and v5 'input'\n          const args = toolCall.args ?? toolCall.input;\n\n          let argsString: string;\n          if (typeof args === 'string') {\n            argsString = args;\n          } else if (args !== undefined && args !== null) {\n            argsString = JSON.stringify(args);\n          } else {\n            argsString = '{}';\n          }\n\n          return {\n            id: toolCallId,\n            type: 'function' as const,\n            function: {\n              name: toolName,\n              arguments: argsString,\n            },\n          };\n        });\n      }\n\n      return result;\n    }\n\n    // For tool messages, convert to OpenAI tool message format\n    if (role === 'tool') {\n      const toolResult = content.find((part): part is AISDKToolResultPart => part?.type === 'tool-result');\n      if (toolResult) {\n        // Support both v4 'result' and v5 'output' fields\n        const resultData = toolResult.output ?? toolResult.result;\n        const resultContent = serializeToolResult(resultData);\n\n        return {\n          role: 'tool',\n          content: resultContent,\n          tool_call_id: toolResult.toolCallId,\n        } as OpenAIMessage;\n      }\n    }\n  }\n\n  return message;\n}\n","import type { UsageStats } from '@mastra/core/observability';\n\n/**\n * BraintrustUsageMetrics\n *\n * Canonical metric keys expected by Braintrust for LLM usage accounting.\n */\nexport interface BraintrustUsageMetrics {\n  prompt_tokens?: number;\n  completion_tokens?: number;\n  tokens?: number;\n  completion_reasoning_tokens?: number;\n  prompt_cached_tokens?: number;\n  prompt_cache_creation_tokens?: number;\n}\n\n/**\n * Formats UsageStats to Braintrust's expected metric format.\n */\nexport function formatUsageMetrics(usage?: UsageStats): BraintrustUsageMetrics {\n  const metrics: BraintrustUsageMetrics = {};\n\n  if (usage?.inputTokens !== undefined) {\n    metrics.prompt_tokens = usage.inputTokens;\n  }\n\n  if (usage?.outputTokens !== undefined) {\n    metrics.completion_tokens = usage.outputTokens;\n  }\n\n  // Compute total if we have both\n  if (metrics.prompt_tokens !== undefined && metrics.completion_tokens !== undefined) {\n    metrics.tokens = metrics.prompt_tokens + metrics.completion_tokens;\n  }\n\n  if (usage?.outputDetails?.reasoning !== undefined) {\n    metrics.completion_reasoning_tokens = usage.outputDetails.reasoning;\n  }\n\n  if (usage?.inputDetails?.cacheRead !== undefined) {\n    metrics.prompt_cached_tokens = usage.inputDetails.cacheRead;\n  }\n\n  if (usage?.inputDetails?.cacheWrite !== undefined) {\n    metrics.prompt_cache_creation_tokens = usage.inputDetails.cacheWrite;\n  }\n\n  return metrics;\n}\n","/**\n * Thread view reconstruction for Braintrust.\n *\n * Reconstructs LLM output in OpenAI Chat Completion format by examining\n * child MODEL_STEP and TOOL_CALL spans. This enables Braintrust's Thread\n * view to properly display the full conversation flow including tool calls.\n *\n * See THREAD_VIEW_RECONSTRUCTION.md for details.\n */\n\nimport { removeNullish } from './formatter';\nimport type { OpenAIMessage } from './formatter';\n\n// ==============================================================================\n// Thread view reconstruction types\n// ==============================================================================\n\n/**\n * Tool call data accumulated from MODEL_STEP and TOOL_CALL spans\n */\nexport interface ThreadToolCall {\n  toolCallId: string;\n  toolName: string;\n  args: unknown;\n  result?: unknown; // filled in when TOOL_CALL ends\n  startTime?: Date; // from TOOL_CALL span, for ordering multiple tool calls within a step\n}\n\n/**\n * Step data accumulated from MODEL_STEP spans for Thread view reconstruction\n */\nexport interface ThreadStepData {\n  stepSpanId: string;\n  stepIndex: number; // for ordering steps correctly\n  text?: string;\n  toolCalls?: ThreadToolCall[];\n}\n\n/**\n * Accumulated data for reconstructing Braintrust Thread view.\n * Populated for MODEL_GENERATION spans as child MODEL_STEP and TOOL_CALL spans complete.\n */\nexport type ThreadData = ThreadStepData[];\n\n/**\n * Tool result data stored when TOOL_CALL spans end (before MODEL_STEP ends)\n */\nexport interface PendingToolResult {\n  result: unknown;\n  startTime: Date;\n}\n\n// ==============================================================================\n// Thread view reconstruction\n// ==============================================================================\n\n/**\n * Reconstruct the Thread view output from accumulated threadData.\n * Converts to OpenAI Chat Completion message format.\n */\nexport function reconstructThreadOutput(threadData: ThreadData, originalOutput: unknown): OpenAIMessage[] {\n  const messages: OpenAIMessage[] = [];\n\n  // Sort steps by stepIndex\n  const sortedSteps = [...threadData].sort((a, b) => a.stepIndex - b.stepIndex);\n\n  for (const step of sortedSteps) {\n    // Sort tool calls by startTime within each step\n    const sortedToolCalls = step.toolCalls\n      ? [...step.toolCalls].sort((a, b) => {\n          if (!a.startTime || !b.startTime) return 0;\n          return a.startTime.getTime() - b.startTime.getTime();\n        })\n      : [];\n\n    if (sortedToolCalls.length > 0) {\n      // Add assistant message with tool_calls\n      messages.push({\n        role: 'assistant',\n        content: step.text || '',\n        tool_calls: sortedToolCalls.map(tc => {\n          // Clean null/undefined values from args before stringifying\n          const cleanArgs =\n            tc.args && typeof tc.args === 'object' && !Array.isArray(tc.args)\n              ? removeNullish(tc.args as Record<string, unknown>)\n              : tc.args;\n          return {\n            id: tc.toolCallId,\n            type: 'function' as const,\n            function: {\n              name: tc.toolName,\n              arguments: typeof cleanArgs === 'string' ? cleanArgs : JSON.stringify(cleanArgs),\n            },\n          };\n        }),\n      });\n\n      // Add tool messages for each result\n      for (const tc of sortedToolCalls) {\n        if (tc.result !== undefined) {\n          messages.push({\n            role: 'tool',\n            content: typeof tc.result === 'string' ? tc.result : JSON.stringify(tc.result),\n            tool_call_id: tc.toolCallId,\n          });\n        }\n      }\n    } else if (step.text) {\n      // Step with text only (final response)\n      messages.push({\n        role: 'assistant',\n        content: step.text,\n      });\n    }\n  }\n\n  // If we have messages and the last one is a tool message,\n  // add the final assistant text from original output\n  if (messages.length > 0) {\n    const lastMessage = messages[messages.length - 1]!;\n    const originalText = (originalOutput as { text?: string })?.text;\n\n    // If the last message is a tool response and we have final text, add it\n    if (originalText && lastMessage.role === 'tool') {\n      messages.push({\n        role: 'assistant',\n        content: originalText,\n      });\n    }\n  }\n\n  return messages;\n}\n","/**\n * Braintrust Exporter for Mastra Observability\n *\n * This exporter sends observability data to Braintrust.\n * Root spans become top-level Braintrust spans (no trace wrapper).\n * Events are handled as zero-duration spans with matching start/end times.\n */\n\nimport type { AnyExportedSpan, ModelGenerationAttributes, ScoreEvent, SpanErrorInfo } from '@mastra/core/observability';\nimport { SpanType } from '@mastra/core/observability';\nimport { omitKeys } from '@mastra/core/utils';\nimport { TrackingExporter } from '@mastra/observability';\nimport type { TraceData, TrackingExporterConfig } from '@mastra/observability';\nimport { initLogger, currentSpan } from 'braintrust';\nimport type { Span, Logger } from 'braintrust';\nimport { removeNullish, convertAISDKMessage } from './formatter';\nimport { formatUsageMetrics } from './metrics';\nimport { reconstructThreadOutput } from './thread-reconstruction';\nimport type { ThreadData, ThreadStepData, PendingToolResult } from './thread-reconstruction';\n\n/**\n * Extended Braintrust span data that includes span type and thread reconstruction data\n */\ninterface BraintrustSpanData {\n  span: Span;\n  spanType: SpanType;\n  threadData?: ThreadData; // only populated for MODEL_GENERATION spans\n  // Tool results stored when TOOL_CALL ends (may arrive before MODEL_STEP ends)\n  pendingToolResults?: Map<string, PendingToolResult>; // keyed by toolCallId\n}\n\nexport interface BraintrustExporterConfig extends TrackingExporterConfig {\n  /**\n   * Optional Braintrust logger instance.\n   * When provided, enables integration with Braintrust contexts such as:\n   * - Evals: Agent traces nest inside eval task spans\n   * - logger.traced(): Agent traces nest inside traced spans\n   * - Parent spans: Auto-detects and attaches to external Braintrust spans\n   */\n  braintrustLogger?: Logger<true>;\n\n  /**\n   * Optional resolver for the active Braintrust span.\n   *\n   * Pass Braintrust's `currentSpan` from the same package instance that creates\n   * `Eval()` or `logger.traced()` spans when your app and Mastra may resolve\n   * different copies of the `braintrust` package.\n   */\n  currentSpan?: () => Span | undefined;\n\n  /** Braintrust API key. Required if logger is not provided. */\n  apiKey?: string;\n  /** Optional custom endpoint */\n  endpoint?: string;\n  /** Braintrust project name (default: 'mastra-tracing') */\n  projectName?: string;\n  /** Support tuning parameters */\n  tuningParameters?: Record<string, any>;\n}\n\ntype BraintrustRoot = Logger<true> | Span;\ntype BraintrustSpan = BraintrustSpanData;\ntype BraintrustEvent = Span;\ntype BraintrustMetadata = unknown;\ntype BraintrustTraceData = TraceData<BraintrustRoot, BraintrustSpan, BraintrustEvent, BraintrustMetadata>;\n\n// Default span type for all spans\nconst DEFAULT_SPAN_TYPE = 'task';\n\n// Exceptions to the default mapping\nconst SPAN_TYPE_EXCEPTIONS: Partial<Record<SpanType, string>> = {\n  [SpanType.MODEL_GENERATION]: 'llm',\n  [SpanType.TOOL_CALL]: 'tool',\n  [SpanType.MCP_TOOL_CALL]: 'tool',\n  [SpanType.WORKFLOW_CONDITIONAL_EVAL]: 'function',\n  [SpanType.WORKFLOW_WAIT_EVENT]: 'function',\n};\n\n// Mapping function - returns valid Braintrust span types\nfunction mapSpanType(spanType: SpanType): 'llm' | 'score' | 'function' | 'eval' | 'task' | 'tool' {\n  return (SPAN_TYPE_EXCEPTIONS[spanType] as any) ?? DEFAULT_SPAN_TYPE;\n}\n\nexport class BraintrustExporter extends TrackingExporter<\n  BraintrustRoot,\n  BraintrustSpan,\n  BraintrustEvent,\n  BraintrustMetadata,\n  BraintrustExporterConfig\n> {\n  name = 'braintrust';\n\n  // Flags and logger for context-aware mode\n  #useProvidedLogger: boolean;\n  #providedLogger?: Logger<true>;\n  #localLogger?: Logger<true>;\n\n  constructor(config: BraintrustExporterConfig = {}) {\n    // Resolve env vars BEFORE calling super (config is readonly in base class)\n    const resolvedApiKey = config.apiKey ?? process.env.BRAINTRUST_API_KEY;\n    const resolvedEndpoint = config.endpoint ?? process.env.BRAINTRUST_ENDPOINT;\n\n    super({\n      ...config,\n      apiKey: resolvedApiKey,\n      endpoint: resolvedEndpoint,\n    });\n\n    this.#useProvidedLogger = !!config.braintrustLogger;\n\n    if (this.#useProvidedLogger) {\n      // Use provided logger - enables Braintrust context integration\n      this.#providedLogger = config.braintrustLogger;\n    } else {\n      // Validate apiKey for creating loggers per trace\n      if (!this.config.apiKey) {\n        this.setDisabled(\n          `Missing required API key. Set BRAINTRUST_API_KEY environment variable or pass apiKey in config.`,\n        );\n        return;\n      }\n      // lazy create logger on first rootSpan\n      this.#localLogger = undefined;\n    }\n  }\n\n  private async getLocalLogger(): Promise<Logger<true> | undefined> {\n    if (this.#localLogger) {\n      return this.#localLogger;\n    }\n    try {\n      const logger = await initLogger({\n        projectName: this.config.projectName ?? 'mastra-tracing',\n        apiKey: this.config.apiKey,\n        appUrl: this.config.endpoint,\n        ...this.config.tuningParameters,\n      });\n      this.#localLogger = logger;\n      return logger;\n    } catch (err) {\n      this.logger.error('Braintrust exporter: Failed to initialize logger', { error: err });\n      this.setDisabled('Failed to initialize Braintrust logger');\n    }\n  }\n\n  async onScoreEvent(event: ScoreEvent): Promise<void> {\n    if (this.isDisabled) return;\n\n    const { score } = event;\n    const rowId = score.spanId ?? score.traceId;\n    if (!rowId) {\n      this.logger.debug('Braintrust exporter: skipping score with no spanId or traceId', {\n        scorerId: score.scorerId,\n      });\n      return;\n    }\n\n    const logger = this.#useProvidedLogger ? this.#providedLogger : await this.getLocalLogger();\n    if (!logger) return;\n\n    const name = score.scorerName ?? score.scorerId;\n\n    try {\n      logger.logFeedback({\n        id: rowId,\n        scores: { [name]: score.score },\n        ...(score.reason ? { comment: score.reason } : {}),\n        metadata: {\n          scorerId: score.scorerId,\n          ...(score.scoreSource ? { scoreSource: score.scoreSource } : {}),\n          ...(score.metadata ?? {}),\n        },\n        source: 'external',\n      });\n    } catch (err) {\n      this.logger.error('Braintrust exporter: Failed to submit score', {\n        error: err,\n        traceId: score.traceId,\n        spanId: score.spanId,\n        scorerId: score.scorerId,\n      });\n    }\n  }\n\n  private startSpan(args: { parent: Span | Logger<true>; span: AnyExportedSpan }): BraintrustSpanData {\n    const { parent, span } = args;\n    const payload = this.buildSpanPayload(span);\n\n    // Braintrust's startSpan() accepts data properties via the `event` parameter\n    // which maps to StartSpanEventArgs (ExperimentLogPartialArgs & Partial<IdField>)\n    // This includes: input, output, metadata, metrics, tags, scores, error, etc.\n    const braintrustSpan = parent.startSpan({\n      spanId: span.id,\n      name: span.name,\n      type: mapSpanType(span.type),\n      startTime: span.startTime.getTime() / 1000,\n      event: {\n        id: span.id, // Use Mastra span ID as Braintrust row ID for logFeedback() compatibility\n        ...payload,\n      },\n    });\n\n    // Create BraintrustSpanData with span type for tree walking\n    // Initialize threadData and pendingToolResults for MODEL_GENERATION spans (used for Thread view reconstruction)\n    const isModelGeneration = span.type === SpanType.MODEL_GENERATION;\n    return {\n      span: braintrustSpan,\n      spanType: span.type,\n      threadData: isModelGeneration ? [] : undefined,\n      pendingToolResults: isModelGeneration ? new Map() : undefined,\n    };\n  }\n\n  protected override async _buildRoot(_args: {\n    span: AnyExportedSpan;\n    traceData: BraintrustTraceData;\n  }): Promise<BraintrustRoot | undefined> {\n    if (this.#useProvidedLogger) {\n      // Try to find a Braintrust span to attach to:\n      // 1. Auto-detect from Braintrust's current span (logger.traced(), Eval(), etc.)\n      // 2. Fall back to the configured logger\n      let externalSpan: Span | undefined;\n      try {\n        externalSpan = this.config.currentSpan?.();\n      } catch (err) {\n        this.logger.error('Braintrust exporter: Failed to resolve configured currentSpan', { error: err });\n      }\n      externalSpan ??= currentSpan();\n\n      // Check if it's a valid span (not the NOOP_SPAN)\n      if (externalSpan && externalSpan.id) {\n        // External span detected - attach Mastra traces to it\n        return externalSpan;\n      } else {\n        // No external span - use provided logger\n        return this.#providedLogger!;\n      }\n    } else {\n      // Use the local logger\n      return this.getLocalLogger();\n    }\n  }\n\n  protected override async _buildSpan(args: {\n    span: AnyExportedSpan;\n    traceData: BraintrustTraceData;\n  }): Promise<BraintrustSpanData | undefined> {\n    const { span, traceData } = args;\n\n    if (span.isRootSpan) {\n      const root = traceData.getRoot();\n      if (root) {\n        return this.startSpan({ parent: root, span });\n      }\n    } else {\n      const parent = traceData.getParent(args);\n      if (parent) {\n        // Parent could be BraintrustSpanData (has .span) or BraintrustRoot (Logger/Span, no .span)\n        const parentSpan = 'span' in parent ? parent.span : parent;\n        return this.startSpan({ parent: parentSpan, span });\n      }\n    }\n  }\n\n  protected override async _buildEvent(args: {\n    span: AnyExportedSpan;\n    traceData: BraintrustTraceData;\n  }): Promise<Span | undefined> {\n    const spanData = await this._buildSpan(args);\n\n    if (!spanData) {\n      // parent doesn't exist and not creating rootSpan, return early data\n      return;\n    }\n\n    spanData.span.end({ endTime: args.span.startTime.getTime() / 1000 });\n    return spanData.span;\n  }\n\n  protected override async _updateSpan(args: { span: AnyExportedSpan; traceData: BraintrustTraceData }): Promise<void> {\n    const { span, traceData } = args;\n\n    const spanData = traceData.getSpan({ spanId: span.id });\n    if (!spanData) {\n      return;\n    }\n    spanData.span.log(this.buildSpanPayload(span, false));\n  }\n\n  protected override async _finishSpan(args: { span: AnyExportedSpan; traceData: BraintrustTraceData }): Promise<void> {\n    const { span, traceData } = args;\n\n    const spanData = traceData.getSpan({ spanId: span.id });\n    if (!spanData) {\n      return;\n    }\n\n    // Handle thread data accumulation for MODEL_STEP and TOOL_CALL spans\n    if (span.type === SpanType.MODEL_STEP) {\n      this.accumulateModelStepData(span, traceData);\n    } else if (span.type === SpanType.TOOL_CALL) {\n      this.accumulateToolCallResult(span, traceData);\n    }\n\n    // Build payload - for MODEL_GENERATION, may reconstruct output from threadData\n    const payload =\n      span.type === SpanType.MODEL_GENERATION\n        ? this.buildModelGenerationPayload(span, spanData)\n        : this.buildSpanPayload(span, false);\n\n    spanData.span.log(payload);\n\n    if (span.endTime) {\n      spanData.span.end({ endTime: span.endTime.getTime() / 1000 });\n    } else {\n      spanData.span.end();\n    }\n  }\n\n  protected override async _abortSpan(args: { span: BraintrustSpan; reason: SpanErrorInfo }): Promise<void> {\n    const { span: spanData, reason } = args;\n    spanData.span.log({\n      error: reason.message,\n      metadata: { errorDetails: reason },\n    });\n    spanData.span.end();\n  }\n\n  // ==============================================================================\n  // Thread view reconstruction helpers\n  // ==============================================================================\n\n  /**\n   * Walk up the tree to find the MODEL_GENERATION ancestor span.\n   * Returns the BraintrustSpanData if found, undefined otherwise.\n   */\n  private findModelGenerationAncestor(spanId: string, traceData: BraintrustTraceData): BraintrustSpanData | undefined {\n    let currentId: string | undefined = spanId;\n\n    while (currentId) {\n      const parentId = traceData.getParentId({ spanId: currentId });\n      if (!parentId) return undefined;\n\n      const parentSpanData = traceData.getSpan({ spanId: parentId });\n      if (parentSpanData?.spanType === SpanType.MODEL_GENERATION) {\n        return parentSpanData;\n      }\n      currentId = parentId;\n    }\n\n    return undefined;\n  }\n\n  /**\n   * Accumulate MODEL_STEP data to the parent MODEL_GENERATION's threadData.\n   * Called when a MODEL_STEP span ends.\n   */\n  private accumulateModelStepData(span: AnyExportedSpan, traceData: BraintrustTraceData): void {\n    const modelGenSpanData = this.findModelGenerationAncestor(span.id, traceData);\n    if (!modelGenSpanData?.threadData) {\n      return;\n    }\n\n    // Extract step data from MODEL_STEP output and attributes\n    const output = span.output as\n      | { text?: string; toolCalls?: Array<{ toolCallId: string; toolName: string; args: unknown }> }\n      | undefined;\n    const attributes = span.attributes as { stepIndex?: number } | undefined;\n\n    const stepData: ThreadStepData = {\n      stepSpanId: span.id,\n      stepIndex: attributes?.stepIndex ?? 0,\n      text: output?.text,\n      toolCalls: output?.toolCalls?.map(tc => ({\n        toolCallId: tc.toolCallId,\n        toolName: tc.toolName,\n        args: tc.args,\n      })),\n    };\n\n    modelGenSpanData.threadData.push(stepData);\n  }\n\n  /**\n   * Store TOOL_CALL result in parent MODEL_GENERATION's pendingToolResults.\n   * Called when a TOOL_CALL span ends.\n   * Results are merged into threadData when MODEL_GENERATION ends.\n   */\n  private accumulateToolCallResult(span: AnyExportedSpan, traceData: BraintrustTraceData): void {\n    const modelGenSpanData = this.findModelGenerationAncestor(span.id, traceData);\n    if (!modelGenSpanData?.pendingToolResults) {\n      return;\n    }\n\n    // Extract tool call ID from TOOL_CALL span input\n    const input = span.input as { toolCallId?: string } | undefined;\n    const toolCallId = input?.toolCallId;\n    if (!toolCallId) {\n      return;\n    }\n\n    // Store the result for later merging\n    modelGenSpanData.pendingToolResults.set(toolCallId, {\n      result: span.output,\n      startTime: span.startTime,\n    });\n  }\n\n  /**\n   * Build the payload for MODEL_GENERATION span, reconstructing output from threadData if available.\n   */\n  private buildModelGenerationPayload(span: AnyExportedSpan, spanData: BraintrustSpanData): Record<string, any> {\n    const basePayload = this.buildSpanPayload(span, false);\n\n    // Check if we have threadData with tool calls to reconstruct\n    const threadData = spanData.threadData;\n    if (!threadData || threadData.length === 0) {\n      return basePayload;\n    }\n\n    // Merge pending tool results into threadData\n    if (spanData.pendingToolResults && spanData.pendingToolResults.size > 0) {\n      for (const step of threadData) {\n        if (step.toolCalls) {\n          for (const toolCall of step.toolCalls) {\n            const pendingResult = spanData.pendingToolResults.get(toolCall.toolCallId);\n            if (pendingResult) {\n              toolCall.result = pendingResult.result;\n              toolCall.startTime = pendingResult.startTime;\n            }\n          }\n        }\n      }\n    }\n\n    // Check if any step has tool calls\n    const hasToolCalls = threadData.some(step => step.toolCalls && step.toolCalls.length > 0);\n    if (!hasToolCalls) {\n      return basePayload;\n    }\n\n    // Reconstruct output as OpenAI messages\n    const reconstructedOutput = reconstructThreadOutput(threadData, span.output);\n    return {\n      ...basePayload,\n      output: reconstructedOutput,\n    };\n  }\n\n  /**\n   * Transforms MODEL_GENERATION input to Braintrust Thread view format.\n   * Converts AI SDK messages (v4/v5) to OpenAI Chat Completion format, which Braintrust requires\n   * for proper rendering of threads (fixes #11023).\n   */\n  private transformInput(input: unknown, spanType: SpanType): unknown {\n    if (spanType === SpanType.MODEL_GENERATION) {\n      // If input is already an array of messages, convert AI SDK format to OpenAI format\n      if (Array.isArray(input)) {\n        return input.map((msg: unknown) => convertAISDKMessage(msg));\n      }\n\n      // If input has a messages array\n      if (\n        input &&\n        typeof input === 'object' &&\n        'messages' in input &&\n        Array.isArray((input as { messages: unknown[] }).messages)\n      ) {\n        return (input as { messages: unknown[] }).messages.map((msg: unknown) => convertAISDKMessage(msg));\n      }\n    }\n\n    return input;\n  }\n\n  /**\n   * Transforms MODEL_GENERATION output to Braintrust Thread view format.\n   */\n  private transformOutput(output: any, spanType: SpanType): any {\n    if (spanType === SpanType.MODEL_GENERATION) {\n      if (!output || typeof output !== 'object') {\n        return output;\n      }\n      const { text, ...rest } = output;\n      // Remove null/undefined values from rest to keep Thread view clean\n      return { role: 'assistant', content: text, ...removeNullish(rest) };\n    }\n\n    return output;\n  }\n\n  private buildSpanPayload(span: AnyExportedSpan, isCreate = true): Record<string, any> {\n    const payload: Record<string, any> = {};\n\n    if (span.input !== undefined) {\n      payload.input = this.transformInput(span.input, span.type);\n    }\n\n    if (span.output !== undefined) {\n      payload.output = this.transformOutput(span.output, span.type);\n    }\n\n    if (isCreate && span.isRootSpan && span.tags?.length) {\n      payload.tags = span.tags;\n    }\n\n    // Initialize metrics and metadata objects\n    payload.metrics = {};\n    // Spread span.metadata first, then set spanType to prevent accidental override\n    payload.metadata = {\n      ...span.metadata,\n      spanType: span.type,\n    };\n\n    if (isCreate) {\n      payload.metadata['mastra-trace-id'] = span.traceId;\n    }\n\n    const attributes = (span.attributes ?? {}) as Record<string, any>;\n\n    if (span.type === SpanType.MODEL_GENERATION) {\n      const modelAttr = attributes as ModelGenerationAttributes;\n\n      // Model goes to metadata\n      if (modelAttr.model !== undefined) {\n        payload.metadata.model = modelAttr.model;\n      }\n\n      // Provider goes to metadata (if provided by attributes)\n      if (modelAttr.provider !== undefined) {\n        payload.metadata.provider = modelAttr.provider;\n      }\n\n      // Prefer resolved model ID (e.g. \"claude-sonnet-4-5-20250929\") over\n      // gateway aliases (e.g. \"claude-sonnet-4.5\") for accurate cost estimation\n      if (modelAttr.responseModel !== undefined) {\n        payload.metadata.model = modelAttr.responseModel;\n      }\n\n      // Usage/token info goes to metrics\n      payload.metrics = formatUsageMetrics(modelAttr.usage);\n\n      // Time to first token (TTFT) for streaming responses\n      // Braintrust expects TTFT in seconds (not milliseconds)\n      if (modelAttr.completionStartTime) {\n        payload.metrics.time_to_first_token =\n          (modelAttr.completionStartTime.getTime() - span.startTime.getTime()) / 1000;\n      }\n\n      // Model parameters go to metadata\n      if (modelAttr.parameters !== undefined) {\n        payload.metadata.modelParameters = modelAttr.parameters;\n      }\n\n      // Other LLM attributes go to metadata\n      const otherAttributes = omitKeys(attributes, [\n        'model',\n        'responseModel',\n        'usage',\n        'parameters',\n        'completionStartTime',\n      ]);\n      payload.metadata = {\n        ...payload.metadata,\n        ...otherAttributes,\n      };\n    } else {\n      // For non-LLM spans, put all attributes in metadata\n      payload.metadata = {\n        ...payload.metadata,\n        ...attributes,\n      };\n    }\n\n    // Handle errors\n    if (span.errorInfo) {\n      payload.error = span.errorInfo.message;\n      payload.metadata.errorDetails = span.errorInfo;\n    }\n\n    // Clean up empty metrics object\n    if (Object.keys(payload.metrics).length === 0) {\n      delete payload.metrics;\n    }\n\n    // Remove null/undefined values from metadata to keep Braintrust UI clean\n    payload.metadata = removeNullish(payload.metadata);\n\n    return payload;\n  }\n}\n"]}