'use strict';

var chunkC73WLCY3_cjs = require('./chunk-C73WLCY3.cjs');
var chunkKXCUCBEI_cjs = require('./chunk-KXCUCBEI.cjs');
var chunkV5WKCX3G_cjs = require('./chunk-V5WKCX3G.cjs');

// src/ai-tracing/no-op.ts
var NoOpAISpan = class _NoOpAISpan {
  id;
  name;
  type;
  attributes;
  parent;
  trace;
  traceId;
  startTime;
  endTime;
  isEvent;
  aiTracing;
  input;
  output;
  errorInfo;
  metadata;
  constructor(options, aiTracing) {
    this.id = "no-op";
    this.name = options.name;
    this.type = options.type;
    this.attributes = options.attributes || {};
    this.metadata = options.metadata;
    this.parent = options.parent;
    this.trace = options.parent ? options.parent.trace : this;
    this.traceId = "no-op-trace";
    this.startTime = /* @__PURE__ */ new Date();
    this.aiTracing = aiTracing;
    this.input = options.input;
    this.output = options.isEvent ? options.output : void 0;
    this.isEvent = options.isEvent;
  }
  end(_options) {
  }
  error(_options) {
  }
  createChildSpan(options) {
    return new _NoOpAISpan({ ...options, parent: this, isEvent: false }, this.aiTracing);
  }
  createEventSpan(options) {
    return new _NoOpAISpan({ ...options, parent: this, isEvent: true }, this.aiTracing);
  }
  update(_options) {
  }
  get isRootSpan() {
    return !this.parent;
  }
};

// src/ai-tracing/types.ts
var AISpanType = /* @__PURE__ */ ((AISpanType2) => {
  AISpanType2["AGENT_RUN"] = "agent_run";
  AISpanType2["GENERIC"] = "generic";
  AISpanType2["LLM_GENERATION"] = "llm_generation";
  AISpanType2["LLM_CHUNK"] = "llm_chunk";
  AISpanType2["MCP_TOOL_CALL"] = "mcp_tool_call";
  AISpanType2["TOOL_CALL"] = "tool_call";
  AISpanType2["WORKFLOW_RUN"] = "workflow_run";
  AISpanType2["WORKFLOW_STEP"] = "workflow_step";
  AISpanType2["WORKFLOW_CONDITIONAL"] = "workflow_conditional";
  AISpanType2["WORKFLOW_CONDITIONAL_EVAL"] = "workflow_conditional_eval";
  AISpanType2["WORKFLOW_PARALLEL"] = "workflow_parallel";
  AISpanType2["WORKFLOW_LOOP"] = "workflow_loop";
  AISpanType2["WORKFLOW_SLEEP"] = "workflow_sleep";
  AISpanType2["WORKFLOW_WAIT_EVENT"] = "workflow_wait_event";
  return AISpanType2;
})(AISpanType || {});
var SamplingStrategyType = /* @__PURE__ */ ((SamplingStrategyType2) => {
  SamplingStrategyType2["ALWAYS"] = "always";
  SamplingStrategyType2["NEVER"] = "never";
  SamplingStrategyType2["RATIO"] = "ratio";
  SamplingStrategyType2["CUSTOM"] = "custom";
  return SamplingStrategyType2;
})(SamplingStrategyType || {});
var AITracingEventType = /* @__PURE__ */ ((AITracingEventType2) => {
  AITracingEventType2["SPAN_STARTED"] = "span_started";
  AITracingEventType2["SPAN_UPDATED"] = "span_updated";
  AITracingEventType2["SPAN_ENDED"] = "span_ended";
  return AITracingEventType2;
})(AITracingEventType || {});

// src/ai-tracing/base.ts
var MastraAITracing = class extends chunkKXCUCBEI_cjs.MastraBase {
  config;
  constructor(config) {
    super({ component: chunkV5WKCX3G_cjs.RegisteredLogger.AI_TRACING, name: config.serviceName });
    this.config = {
      serviceName: config.serviceName,
      instanceName: config.instanceName,
      sampling: config.sampling ?? { type: "always" /* ALWAYS */ },
      exporters: config.exporters ?? [],
      processors: config.processors ?? []
    };
  }
  /**
   * Override setLogger to add AI tracing specific initialization log
   */
  __setLogger(logger) {
    super.__setLogger(logger);
    this.logger.debug(
      `[AI Tracing] Initialized [service=${this.config.serviceName}] [instance=${this.config.instanceName}] [sampling=${this.config.sampling.type}]`
    );
  }
  // ============================================================================
  // Protected getters for clean config access
  // ============================================================================
  get exporters() {
    return this.config.exporters || [];
  }
  get processors() {
    return this.config.processors || [];
  }
  // ============================================================================
  // Public API - Single type-safe span creation method
  // ============================================================================
  /**
   * Start a new span of a specific AISpanType
   */
  startSpan(options) {
    const { type, name, input, output, attributes, metadata, parent, startOptions, isEvent } = options;
    const { runtimeContext } = startOptions || {};
    if (!this.shouldSample({ runtimeContext })) {
      return new NoOpAISpan(
        { type, name, input, output, attributes, metadata, parent, isEvent: isEvent === true },
        this
      );
    }
    const spanOptions = {
      type,
      name,
      input,
      output,
      attributes,
      metadata,
      parent,
      isEvent: isEvent === true
    };
    const span = this.createSpan(spanOptions);
    if (span.isEvent) {
      this.emitSpanEnded(span);
    } else {
      this.wireSpanLifecycle(span);
      this.emitSpanStarted(span);
    }
    return span;
  }
  // ============================================================================
  // Configuration Management
  // ============================================================================
  /**
   * Get current configuration
   */
  getConfig() {
    return { ...this.config };
  }
  // ============================================================================
  // Plugin Access
  // ============================================================================
  /**
   * Get all exporters
   */
  getExporters() {
    return [...this.exporters];
  }
  /**
   * Get all processors
   */
  getProcessors() {
    return [...this.processors];
  }
  /**
   * Get the logger instance (for exporters and other components)
   */
  getLogger() {
    return this.logger;
  }
  // ============================================================================
  // Span Lifecycle Management
  // ============================================================================
  /**
   * Automatically wires up AI tracing lifecycle events for any span
   * This ensures all spans emit events regardless of implementation
   */
  wireSpanLifecycle(span) {
    const originalEnd = span.end.bind(span);
    const originalUpdate = span.update.bind(span);
    span.end = (options) => {
      originalEnd(options);
      this.emitSpanEnded(span);
    };
    span.update = (options) => {
      originalUpdate(options);
      this.emitSpanUpdated(span);
    };
  }
  // ============================================================================
  // Utility Methods
  // ============================================================================
  /**
   * Check if an AI trace should be sampled
   */
  shouldSample(traceContext) {
    const { sampling } = this.config;
    switch (sampling.type) {
      case "always" /* ALWAYS */:
        return true;
      case "never" /* NEVER */:
        return false;
      case "ratio" /* RATIO */:
        if (sampling.probability === void 0 || sampling.probability < 0 || sampling.probability > 1) {
          this.logger.warn(
            `Invalid sampling probability: ${sampling.probability}. Expected value between 0 and 1. Defaulting to no sampling.`
          );
          return false;
        }
        return Math.random() < sampling.probability;
      case "custom" /* CUSTOM */:
        return sampling.sampler(traceContext);
      default:
        throw new Error(`Sampling strategy type not implemented: ${sampling.type}`);
    }
  }
  /**
   * Process a span through all processors
   */
  processSpan(span) {
    let processedSpan = span;
    for (const processor of this.processors) {
      if (!processedSpan) {
        break;
      }
      try {
        processedSpan = processor.process(processedSpan);
      } catch (error) {
        this.logger.error(`[AI Tracing] Processor error [name=${processor.name}]`, error);
      }
    }
    return processedSpan;
  }
  // ============================================================================
  // Event-driven Export Methods
  // ============================================================================
  /**
   * Emit a span started event
   */
  emitSpanStarted(span) {
    const processedSpan = this.processSpan(span);
    if (processedSpan) {
      this.exportEvent({ type: "span_started" /* SPAN_STARTED */, span: processedSpan }).catch((error) => {
        this.logger.error("[AI Tracing] Failed to export span_started event", error);
      });
    }
  }
  /**
   * Emit a span ended event (called automatically when spans end)
   */
  emitSpanEnded(span) {
    const processedSpan = this.processSpan(span);
    if (processedSpan) {
      this.exportEvent({ type: "span_ended" /* SPAN_ENDED */, span: processedSpan }).catch((error) => {
        this.logger.error("[AI Tracing] Failed to export span_ended event", error);
      });
    }
  }
  /**
   * Emit a span updated event
   */
  emitSpanUpdated(span) {
    const processedSpan = this.processSpan(span);
    if (processedSpan) {
      this.exportEvent({ type: "span_updated" /* SPAN_UPDATED */, span: processedSpan }).catch((error) => {
        this.logger.error("[AI Tracing] Failed to export span_updated event", error);
      });
    }
  }
  /**
   * Export tracing event through all exporters (realtime mode)
   */
  async exportEvent(event) {
    const exportPromises = this.exporters.map(async (exporter) => {
      try {
        if (exporter.exportEvent) {
          await exporter.exportEvent(event);
          this.logger.debug(`[AI Tracing] Event exported [exporter=${exporter.name}] [type=${event.type}]`);
        }
      } catch (error) {
        this.logger.error(`[AI Tracing] Export error [exporter=${exporter.name}]`, error);
      }
    });
    await Promise.allSettled(exportPromises);
  }
  // ============================================================================
  // Lifecycle Management
  // ============================================================================
  /**
   * Initialize AI tracing (called by Mastra during component registration)
   */
  init() {
    this.logger.debug(`[AI Tracing] Initialization started [name=${this.name}]`);
    this.logger.info(`[AI Tracing] Initialized successfully [name=${this.name}]`);
  }
  /**
   * Shutdown AI tracing and clean up resources
   */
  async shutdown() {
    this.logger.debug(`[AI Tracing] Shutdown started [name=${this.name}]`);
    const shutdownPromises = [...this.exporters.map((e) => e.shutdown()), ...this.processors.map((p) => p.shutdown())];
    await Promise.allSettled(shutdownPromises);
    this.logger.info(`[AI Tracing] Shutdown completed [name=${this.name}]`);
  }
};

// src/ai-tracing/exporters/console.ts
var ConsoleExporter = class {
  name = "tracing-console-exporter";
  logger;
  constructor(logger) {
    if (logger) {
      this.logger = logger;
    } else {
      this.logger = new chunkV5WKCX3G_cjs.ConsoleLogger({ level: chunkV5WKCX3G_cjs.LogLevel.INFO });
    }
  }
  async exportEvent(event) {
    const span = event.span;
    const formatAttributes = (attributes) => {
      try {
        return JSON.stringify(attributes, null, 2);
      } catch (error) {
        const errMsg = error instanceof Error ? error.message : "Unknown formatting error";
        return `[Unable to serialize attributes: ${errMsg}]`;
      }
    };
    const formatDuration = (startTime, endTime) => {
      if (!endTime) return "N/A";
      const duration = endTime.getTime() - startTime.getTime();
      return `${duration}ms`;
    };
    switch (event.type) {
      case "span_started" /* SPAN_STARTED */:
        this.logger.info(`\u{1F680} SPAN_STARTED`);
        this.logger.info(`   Type: ${span.type}`);
        this.logger.info(`   Name: ${span.name}`);
        this.logger.info(`   ID: ${span.id}`);
        this.logger.info(`   Trace ID: ${span.traceId}`);
        if (span.input !== void 0) {
          this.logger.info(`   Input: ${formatAttributes(span.input)}`);
        }
        this.logger.info(`   Attributes: ${formatAttributes(span.attributes)}`);
        this.logger.info("\u2500".repeat(80));
        break;
      case "span_ended" /* SPAN_ENDED */:
        const duration = formatDuration(span.startTime, span.endTime);
        this.logger.info(`\u2705 SPAN_ENDED`);
        this.logger.info(`   Type: ${span.type}`);
        this.logger.info(`   Name: ${span.name}`);
        this.logger.info(`   ID: ${span.id}`);
        this.logger.info(`   Duration: ${duration}`);
        this.logger.info(`   Trace ID: ${span.traceId}`);
        if (span.input !== void 0) {
          this.logger.info(`   Input: ${formatAttributes(span.input)}`);
        }
        if (span.output !== void 0) {
          this.logger.info(`   Output: ${formatAttributes(span.output)}`);
        }
        if (span.errorInfo) {
          this.logger.info(`   Error: ${formatAttributes(span.errorInfo)}`);
        }
        this.logger.info(`   Attributes: ${formatAttributes(span.attributes)}`);
        this.logger.info("\u2500".repeat(80));
        break;
      case "span_updated" /* SPAN_UPDATED */:
        this.logger.info(`\u{1F4DD} SPAN_UPDATED`);
        this.logger.info(`   Type: ${span.type}`);
        this.logger.info(`   Name: ${span.name}`);
        this.logger.info(`   ID: ${span.id}`);
        this.logger.info(`   Trace ID: ${span.traceId}`);
        if (span.input !== void 0) {
          this.logger.info(`   Input: ${formatAttributes(span.input)}`);
        }
        if (span.output !== void 0) {
          this.logger.info(`   Output: ${formatAttributes(span.output)}`);
        }
        if (span.errorInfo) {
          this.logger.info(`   Error: ${formatAttributes(span.errorInfo)}`);
        }
        this.logger.info(`   Updated Attributes: ${formatAttributes(span.attributes)}`);
        this.logger.info("\u2500".repeat(80));
        break;
      default:
        this.logger.warn(`Tracing event type not implemented: ${event.type}`);
    }
  }
  async shutdown() {
    this.logger.info("ConsoleExporter shutdown");
  }
};

// src/ai-tracing/exporters/default.ts
function resolveStrategy(userConfig, storage, logger) {
  if (userConfig.strategy && userConfig.strategy !== "auto") {
    const hints = storage.aiTracingStrategy;
    if (hints.supported.includes(userConfig.strategy)) {
      return userConfig.strategy;
    }
    logger.warn("User-specified AI tracing strategy not supported by storage adapter, falling back to auto-selection", {
      userStrategy: userConfig.strategy,
      storageAdapter: storage.constructor.name,
      supportedStrategies: hints.supported,
      fallbackStrategy: hints.preferred
    });
  }
  return storage.aiTracingStrategy.preferred;
}
var DefaultExporter = class {
  name = "tracing-default-exporter";
  logger;
  mastra = null;
  config;
  resolvedStrategy;
  buffer;
  flushTimer = null;
  constructor(config = {}, logger) {
    if (logger) {
      this.logger = logger;
    } else {
      this.logger = new chunkV5WKCX3G_cjs.ConsoleLogger({ level: chunkV5WKCX3G_cjs.LogLevel.INFO });
    }
    this.config = {
      maxBatchSize: config.maxBatchSize ?? 1e3,
      maxBufferSize: config.maxBufferSize ?? 1e4,
      maxBatchWaitMs: config.maxBatchWaitMs ?? 5e3,
      maxRetries: config.maxRetries ?? 4,
      retryDelayMs: config.retryDelayMs ?? 500,
      strategy: config.strategy ?? "auto"
    };
    this.buffer = {
      creates: [],
      updates: [],
      insertOnly: [],
      seenSpans: /* @__PURE__ */ new Set(),
      spanSequences: /* @__PURE__ */ new Map(),
      outOfOrderCount: 0,
      totalSize: 0
    };
    this.resolvedStrategy = "batch-with-updates";
  }
  strategyInitialized = false;
  /**
   * Register the Mastra instance (called after Mastra construction is complete)
   */
  __registerMastra(mastra) {
    this.mastra = mastra;
  }
  /**
   * Initialize the exporter (called after all dependencies are ready)
   */
  init() {
    if (!this.mastra) {
      throw new Error("DefaultExporter: init() called before __registerMastra()");
    }
    const storage = this.mastra.getStorage();
    if (!storage) {
      throw new Error("DefaultExporter: Storage not available during initialization");
    }
    this.initializeStrategy(storage);
  }
  /**
   * Initialize the resolved strategy once storage is available
   */
  initializeStrategy(storage) {
    if (this.strategyInitialized) return;
    this.resolvedStrategy = resolveStrategy(this.config, storage, this.logger);
    this.strategyInitialized = true;
    this.logger.info("AI tracing exporter initialized", {
      strategy: this.resolvedStrategy,
      source: this.config.strategy !== "auto" ? "user" : "auto",
      storageAdapter: storage.constructor.name,
      maxBatchSize: this.config.maxBatchSize,
      maxBatchWaitMs: this.config.maxBatchWaitMs
    });
  }
  /**
   * Builds a unique span key for tracking
   */
  buildSpanKey(traceId, spanId) {
    return `${traceId}:${spanId}`;
  }
  /**
   * Gets the next sequence number for a span
   */
  getNextSequence(spanKey) {
    const current = this.buffer.spanSequences.get(spanKey) || 0;
    const next = current + 1;
    this.buffer.spanSequences.set(spanKey, next);
    return next;
  }
  /**
   * Handles out-of-order span updates by logging and skipping
   */
  handleOutOfOrderUpdate(event) {
    this.logger.warn("Out-of-order span update detected - skipping event", {
      spanId: event.span.id,
      traceId: event.span.traceId,
      eventType: event.type
    });
  }
  /**
   * Adds an event to the appropriate buffer based on strategy
   */
  addToBuffer(event) {
    const spanKey = this.buildSpanKey(event.span.traceId, event.span.id);
    if (this.buffer.totalSize === 0) {
      this.buffer.firstEventTime = /* @__PURE__ */ new Date();
    }
    switch (event.type) {
      case "span_started" /* SPAN_STARTED */:
        if (this.resolvedStrategy === "batch-with-updates") {
          const createRecord = {
            traceId: event.span.traceId,
            spanId: event.span.id,
            ...this.buildCreateRecord(event.span),
            createdAt: /* @__PURE__ */ new Date(),
            updatedAt: null
          };
          this.buffer.creates.push(createRecord);
          this.buffer.seenSpans.add(spanKey);
        }
        break;
      case "span_updated" /* SPAN_UPDATED */:
        if (this.resolvedStrategy === "batch-with-updates") {
          if (this.buffer.seenSpans.has(spanKey)) {
            this.buffer.updates.push({
              traceId: event.span.traceId,
              spanId: event.span.id,
              updates: {
                ...this.buildUpdateRecord(event.span),
                updatedAt: /* @__PURE__ */ new Date()
              },
              sequenceNumber: this.getNextSequence(spanKey)
            });
          } else {
            this.handleOutOfOrderUpdate(event);
            this.buffer.outOfOrderCount++;
          }
        }
        break;
      case "span_ended" /* SPAN_ENDED */:
        if (this.resolvedStrategy === "batch-with-updates") {
          if (this.buffer.seenSpans.has(spanKey)) {
            this.buffer.updates.push({
              traceId: event.span.traceId,
              spanId: event.span.id,
              updates: {
                ...this.buildUpdateRecord(event.span),
                updatedAt: /* @__PURE__ */ new Date()
              },
              sequenceNumber: this.getNextSequence(spanKey)
            });
          } else {
            this.handleOutOfOrderUpdate(event);
            this.buffer.outOfOrderCount++;
          }
        } else if (this.resolvedStrategy === "insert-only") {
          const createRecord = {
            traceId: event.span.traceId,
            spanId: event.span.id,
            ...this.buildCreateRecord(event.span),
            createdAt: /* @__PURE__ */ new Date(),
            updatedAt: null
          };
          this.buffer.insertOnly.push(createRecord);
        }
        break;
    }
    this.buffer.totalSize = this.buffer.creates.length + this.buffer.updates.length + this.buffer.insertOnly.length;
  }
  /**
   * Checks if buffer should be flushed based on size or time triggers
   */
  shouldFlush() {
    if (this.buffer.totalSize >= this.config.maxBufferSize) {
      return true;
    }
    if (this.buffer.totalSize >= this.config.maxBatchSize) {
      return true;
    }
    if (this.buffer.firstEventTime && this.buffer.totalSize > 0) {
      const elapsed = Date.now() - this.buffer.firstEventTime.getTime();
      if (elapsed >= this.config.maxBatchWaitMs) {
        return true;
      }
    }
    return false;
  }
  /**
   * Resets the buffer after successful flush
   */
  resetBuffer() {
    this.buffer.creates = [];
    this.buffer.updates = [];
    this.buffer.insertOnly = [];
    this.buffer.seenSpans.clear();
    this.buffer.spanSequences.clear();
    this.buffer.outOfOrderCount = 0;
    this.buffer.firstEventTime = void 0;
    this.buffer.totalSize = 0;
  }
  /**
   * Schedules a flush using setTimeout
   */
  scheduleFlush() {
    if (this.flushTimer) {
      clearTimeout(this.flushTimer);
    }
    this.flushTimer = setTimeout(() => {
      this.flush().catch((error) => {
        this.logger.error("Scheduled flush failed", {
          error: error instanceof Error ? error.message : String(error)
        });
      });
    }, this.config.maxBatchWaitMs);
  }
  /**
   * Serializes span attributes to storage record format
   * Handles all AI span types and their specific attributes
   */
  serializeAttributes(span) {
    if (!span.attributes) {
      return null;
    }
    try {
      return JSON.parse(
        JSON.stringify(span.attributes, (_key, value) => {
          if (value instanceof Date) {
            return value.toISOString();
          }
          if (typeof value === "object" && value !== null) {
            return value;
          }
          return value;
        })
      );
    } catch (error) {
      this.logger.warn("Failed to serialize span attributes, storing as null", {
        spanId: span.id,
        spanType: span.type,
        error: error instanceof Error ? error.message : String(error)
      });
      return null;
    }
  }
  buildCreateRecord(span) {
    return {
      parentSpanId: span.parent?.id ?? null,
      name: span.name,
      scope: null,
      spanType: span.type,
      attributes: this.serializeAttributes(span),
      metadata: span.metadata ?? null,
      links: null,
      startedAt: span.startTime,
      endedAt: span.endTime ?? null,
      input: span.input,
      output: span.output,
      error: span.errorInfo,
      isEvent: span.isEvent
    };
  }
  buildUpdateRecord(span) {
    return {
      name: span.name,
      scope: null,
      attributes: this.serializeAttributes(span),
      metadata: span.metadata ?? null,
      links: null,
      endedAt: span.endTime ?? null,
      input: span.input,
      output: span.output,
      error: span.errorInfo
    };
  }
  /**
   * Handles realtime strategy - processes each event immediately
   */
  async handleRealtimeEvent(event, storage) {
    const span = event.span;
    if (span.isEvent) {
      if (event.type === "span_ended" /* SPAN_ENDED */) {
        await storage.createAISpan({
          traceId: span.traceId,
          spanId: span.id,
          ...this.buildCreateRecord(span),
          createdAt: /* @__PURE__ */ new Date(),
          updatedAt: null
        });
      } else {
        this.logger.warn(`Tracing event type not implemented for event spans: ${event.type}`);
      }
    } else {
      switch (event.type) {
        case "span_started" /* SPAN_STARTED */:
          await storage.createAISpan({
            traceId: span.traceId,
            spanId: span.id,
            ...this.buildCreateRecord(span),
            createdAt: /* @__PURE__ */ new Date(),
            updatedAt: null
          });
          break;
        case "span_updated" /* SPAN_UPDATED */:
        case "span_ended" /* SPAN_ENDED */:
          await storage.updateAISpan({
            traceId: span.traceId,
            spanId: span.id,
            updates: {
              ...this.buildUpdateRecord(span),
              updatedAt: /* @__PURE__ */ new Date()
            }
          });
          break;
        default:
          this.logger.warn(`Tracing event type not implemented for span spans: ${event.type}`);
      }
    }
  }
  /**
   * Handles batch-with-updates strategy - buffers events and processes in batches
   */
  handleBatchWithUpdatesEvent(event) {
    this.addToBuffer(event);
    if (this.shouldFlush()) {
      this.flush().catch((error) => {
        this.logger.error("Batch flush failed", {
          error: error instanceof Error ? error.message : String(error)
        });
      });
    } else if (this.buffer.totalSize === 1) {
      this.scheduleFlush();
    }
  }
  /**
   * Handles insert-only strategy - only processes SPAN_ENDED events in batches
   */
  handleInsertOnlyEvent(event) {
    if (event.type === "span_ended" /* SPAN_ENDED */) {
      this.addToBuffer(event);
      if (this.shouldFlush()) {
        this.flush().catch((error) => {
          this.logger.error("Batch flush failed", {
            error: error instanceof Error ? error.message : String(error)
          });
        });
      } else if (this.buffer.totalSize === 1) {
        this.scheduleFlush();
      }
    }
  }
  /**
   * Calculates retry delay using exponential backoff
   */
  calculateRetryDelay(attempt) {
    return this.config.retryDelayMs * Math.pow(2, attempt);
  }
  /**
   * Flushes the current buffer to storage with retry logic
   */
  async flush() {
    if (!this.mastra) {
      this.logger.warn("Cannot flush traces. Mastra instance not registered yet.");
      return;
    }
    const storage = this.mastra.getStorage();
    if (!storage) {
      this.logger.warn("Cannot flush traces. Mastra storage is not initialized");
      return;
    }
    if (this.flushTimer) {
      clearTimeout(this.flushTimer);
      this.flushTimer = null;
    }
    if (this.buffer.totalSize === 0) {
      return;
    }
    const startTime = Date.now();
    const flushReason = this.buffer.totalSize >= this.config.maxBufferSize ? "overflow" : this.buffer.totalSize >= this.config.maxBatchSize ? "size" : "time";
    const bufferCopy = {
      creates: [...this.buffer.creates],
      updates: [...this.buffer.updates],
      insertOnly: [...this.buffer.insertOnly],
      seenSpans: new Set(this.buffer.seenSpans),
      spanSequences: new Map(this.buffer.spanSequences),
      outOfOrderCount: this.buffer.outOfOrderCount,
      firstEventTime: this.buffer.firstEventTime,
      totalSize: this.buffer.totalSize
    };
    this.resetBuffer();
    await this.flushWithRetries(storage, bufferCopy, 0);
    const elapsed = Date.now() - startTime;
    this.logger.debug("Batch flushed", {
      strategy: this.resolvedStrategy,
      batchSize: bufferCopy.totalSize,
      flushReason,
      durationMs: elapsed,
      outOfOrderCount: bufferCopy.outOfOrderCount > 0 ? bufferCopy.outOfOrderCount : void 0
    });
  }
  /**
   * Attempts to flush with exponential backoff retry logic
   */
  async flushWithRetries(storage, buffer, attempt) {
    try {
      if (this.resolvedStrategy === "batch-with-updates") {
        if (buffer.creates.length > 0) {
          await storage.batchCreateAISpans({ records: buffer.creates });
        }
        if (buffer.updates.length > 0) {
          const sortedUpdates = buffer.updates.sort((a, b) => {
            const spanCompare = this.buildSpanKey(a.traceId, a.spanId).localeCompare(
              this.buildSpanKey(b.traceId, b.spanId)
            );
            if (spanCompare !== 0) return spanCompare;
            return a.sequenceNumber - b.sequenceNumber;
          });
          await storage.batchUpdateAISpans({ records: sortedUpdates });
        }
      } else if (this.resolvedStrategy === "insert-only") {
        if (buffer.insertOnly.length > 0) {
          await storage.batchCreateAISpans({ records: buffer.insertOnly });
        }
      }
    } catch (error) {
      if (attempt < this.config.maxRetries) {
        const retryDelay = this.calculateRetryDelay(attempt);
        this.logger.warn("Batch flush failed, retrying", {
          attempt: attempt + 1,
          maxRetries: this.config.maxRetries,
          nextRetryInMs: retryDelay,
          error: error instanceof Error ? error.message : String(error)
        });
        await new Promise((resolve) => setTimeout(resolve, retryDelay));
        return this.flushWithRetries(storage, buffer, attempt + 1);
      } else {
        this.logger.error("Batch flush failed after all retries, dropping batch", {
          finalAttempt: attempt + 1,
          maxRetries: this.config.maxRetries,
          droppedBatchSize: buffer.totalSize,
          error: error instanceof Error ? error.message : String(error)
        });
      }
    }
  }
  async exportEvent(event) {
    if (!this.mastra) {
      this.logger.warn("Cannot export AI tracing event. Mastra instance not registered yet.");
      return;
    }
    const storage = this.mastra.getStorage();
    if (!storage) {
      this.logger.warn("Cannot store traces. Mastra storage is not initialized");
      return;
    }
    if (!this.strategyInitialized) {
      this.initializeStrategy(storage);
    }
    switch (this.resolvedStrategy) {
      case "realtime":
        await this.handleRealtimeEvent(event, storage);
        break;
      case "batch-with-updates":
        this.handleBatchWithUpdatesEvent(event);
        break;
      case "insert-only":
        this.handleInsertOnlyEvent(event);
        break;
    }
  }
  async shutdown() {
    if (this.flushTimer) {
      clearTimeout(this.flushTimer);
      this.flushTimer = null;
    }
    if (this.buffer.totalSize > 0) {
      this.logger.info("Flushing remaining events on shutdown", {
        remainingEvents: this.buffer.totalSize
      });
      try {
        await this.flush();
      } catch (error) {
        this.logger.error("Failed to flush remaining events during shutdown", {
          error: error instanceof Error ? error.message : String(error)
        });
      }
    }
    this.logger.info("DefaultExporter shutdown complete");
  }
};

// src/ai-tracing/default.ts
function generateSpanId() {
  const bytes = new Uint8Array(8);
  if (typeof crypto !== "undefined" && crypto.getRandomValues) {
    crypto.getRandomValues(bytes);
  } else {
    for (let i = 0; i < 8; i++) {
      bytes[i] = Math.floor(Math.random() * 256);
    }
  }
  return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
}
function generateTraceId() {
  const bytes = new Uint8Array(16);
  if (typeof crypto !== "undefined" && crypto.getRandomValues) {
    crypto.getRandomValues(bytes);
  } else {
    for (let i = 0; i < 16; i++) {
      bytes[i] = Math.floor(Math.random() * 256);
    }
  }
  return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
}
var DefaultAISpan = class {
  id;
  name;
  type;
  attributes;
  parent;
  trace;
  traceId;
  startTime;
  endTime;
  isEvent;
  aiTracing;
  input;
  output;
  errorInfo;
  metadata;
  logger;
  constructor(options, aiTracing) {
    this.id = generateSpanId();
    this.name = options.name;
    this.type = options.type;
    this.attributes = options.attributes || {};
    this.metadata = options.metadata;
    this.parent = options.parent;
    this.trace = options.parent ? options.parent.trace : this;
    this.startTime = /* @__PURE__ */ new Date();
    this.aiTracing = aiTracing;
    this.input = options.input;
    this.isEvent = options.isEvent;
    this.logger = new chunkV5WKCX3G_cjs.ConsoleLogger({
      name: "default-ai-span",
      level: chunkV5WKCX3G_cjs.LogLevel.INFO
      // Set to INFO so that info() calls actually log
    });
    if (!options.parent) {
      this.traceId = generateTraceId();
    } else {
      this.traceId = options.parent.trace.traceId;
    }
    if (this.isEvent) {
      this.output = options.output;
    }
  }
  end(options) {
    if (this.isEvent) {
      this.logger.warn(`End event is not available on event spans`);
      return;
    }
    this.endTime = /* @__PURE__ */ new Date();
    if (options?.output !== void 0) {
      this.output = options.output;
    }
    if (options?.attributes) {
      this.attributes = { ...this.attributes, ...options.attributes };
    }
    if (options?.metadata) {
      this.metadata = { ...this.metadata, ...options.metadata };
    }
  }
  error(options) {
    if (this.isEvent) {
      this.logger.warn(`Error event is not available on event spans`);
      return;
    }
    const { error, endSpan = true, attributes, metadata } = options;
    this.errorInfo = error instanceof chunkC73WLCY3_cjs.MastraError ? {
      id: error.id,
      details: error.details,
      category: error.category,
      domain: error.domain,
      message: error.message
    } : {
      message: error.message
    };
    if (attributes) {
      this.attributes = { ...this.attributes, ...attributes };
    }
    if (metadata) {
      this.metadata = { ...this.metadata, ...metadata };
    }
    if (endSpan) {
      this.end();
    } else {
      this.update({});
    }
  }
  createChildSpan(options) {
    return this.aiTracing.startSpan({
      ...options,
      parent: this,
      isEvent: false
    });
  }
  createEventSpan(options) {
    return this.aiTracing.startSpan({
      ...options,
      parent: this,
      isEvent: true
    });
  }
  update(options) {
    if (this.isEvent) {
      this.logger.warn(`Update() is not available on event spans`);
      return;
    }
    if (options?.input !== void 0) {
      this.input = options.input;
    }
    if (options?.output !== void 0) {
      this.output = options.output;
    }
    if (options?.attributes) {
      this.attributes = { ...this.attributes, ...options.attributes };
    }
    if (options?.metadata) {
      this.metadata = { ...this.metadata, ...options.metadata };
    }
  }
  get isRootSpan() {
    return !this.parent;
  }
  async export() {
    return JSON.stringify({
      id: this.id,
      attributes: this.attributes,
      metadata: this.metadata,
      startTime: this.startTime,
      endTime: this.endTime,
      traceId: this.traceId
      // OpenTelemetry trace ID
    });
  }
};
var SensitiveDataFilter = class {
  name = "sensitive-data-filter";
  sensitiveFields;
  constructor(sensitiveFields) {
    this.sensitiveFields = (sensitiveFields || [
      "password",
      "token",
      "secret",
      "key",
      "apiKey",
      "auth",
      "authorization",
      "bearer",
      "jwt",
      "credential",
      "sessionId"
    ]).map((field) => field.toLowerCase());
  }
  process(span) {
    const deepFilter = (obj, seen = /* @__PURE__ */ new WeakSet()) => {
      if (obj === null || typeof obj !== "object") {
        return obj;
      }
      if (seen.has(obj)) {
        return "[Circular Reference]";
      }
      seen.add(obj);
      if (Array.isArray(obj)) {
        return obj.map((item) => deepFilter(item, seen));
      }
      const filtered = {};
      Object.keys(obj).forEach((key) => {
        if (this.sensitiveFields.includes(key.toLowerCase())) {
          if (obj[key] && typeof obj[key] === "object") {
            filtered[key] = deepFilter(obj[key], seen);
          } else {
            filtered[key] = "[REDACTED]";
          }
        } else {
          filtered[key] = deepFilter(obj[key], seen);
        }
      });
      return filtered;
    };
    try {
      const filteredSpan = { ...span };
      filteredSpan.attributes = deepFilter(span.attributes);
      filteredSpan.metadata = deepFilter(span.metadata);
      filteredSpan.input = deepFilter(span.input);
      filteredSpan.output = deepFilter(span.output);
      filteredSpan.errorInfo = deepFilter(span.errorInfo);
      return filteredSpan;
    } catch (error) {
      const safeSpan = { ...span };
      safeSpan.attributes = {
        "[FILTERING_ERROR]": "Attributes were completely redacted due to filtering error",
        "[ERROR_MESSAGE]": error instanceof Error ? error.message : "Unknown filtering error"
      };
      return safeSpan;
    }
  }
  async shutdown() {
  }
};
var aiTracingDefaultConfig = {
  serviceName: "mastra-ai-service",
  instanceName: "default",
  sampling: { type: "always" /* ALWAYS */ },
  exporters: [new ConsoleExporter()],
  processors: [new SensitiveDataFilter()]
};
var DefaultAITracing = class extends MastraAITracing {
  constructor(config = aiTracingDefaultConfig) {
    super(config);
  }
  // ============================================================================
  // Abstract Method Implementations
  // ============================================================================
  createSpan(options) {
    return new DefaultAISpan(options, this);
  }
};

// src/ai-tracing/registry.ts
var AITracingRegistry = class {
  instances = /* @__PURE__ */ new Map();
  defaultInstance;
  selector;
  /**
   * Register a tracing instance
   */
  register(name, instance, isDefault = false) {
    if (this.instances.has(name)) {
      throw new Error(`AI Tracing instance '${name}' already registered`);
    }
    this.instances.set(name, instance);
    if (isDefault || !this.defaultInstance) {
      this.defaultInstance = instance;
    }
  }
  /**
   * Get a tracing instance by name
   */
  get(name) {
    return this.instances.get(name);
  }
  /**
   * Get the default tracing instance
   */
  getDefault() {
    return this.defaultInstance;
  }
  /**
   * Set the tracing selector function
   */
  setSelector(selector) {
    this.selector = selector;
  }
  /**
   * Get the selected tracing instance based on context
   */
  getSelected(context) {
    if (this.selector) {
      const selected = this.selector(context, this.instances);
      if (selected && this.instances.has(selected)) {
        return this.instances.get(selected);
      }
    }
    return this.defaultInstance;
  }
  /**
   * Unregister a tracing instance
   */
  unregister(name) {
    return this.instances.delete(name);
  }
  /**
   * Shutdown all instances and clear the registry
   */
  async shutdown() {
    const shutdownPromises = Array.from(this.instances.values()).map((instance) => instance.shutdown());
    await Promise.allSettled(shutdownPromises);
    this.instances.clear();
  }
  /**
   * Clear all instances without shutdown
   */
  clear() {
    this.instances.clear();
    this.defaultInstance = void 0;
    this.selector = void 0;
  }
  /**
   * Get all registered instances
   */
  getAll() {
    return new Map(this.instances);
  }
};
var aiTracingRegistry = new AITracingRegistry();
function registerAITracing(name, instance, isDefault = false) {
  aiTracingRegistry.register(name, instance, isDefault);
}
function getAITracing(name) {
  return aiTracingRegistry.get(name);
}
function getDefaultAITracing() {
  return aiTracingRegistry.getDefault();
}
function setAITracingSelector(selector) {
  aiTracingRegistry.setSelector(selector);
}
function getSelectedAITracing(context) {
  return aiTracingRegistry.getSelected(context);
}
function unregisterAITracing(name) {
  return aiTracingRegistry.unregister(name);
}
async function shutdownAITracingRegistry() {
  await aiTracingRegistry.shutdown();
}
function clearAITracingRegistry() {
  aiTracingRegistry.clear();
}
function getAllAITracing() {
  return aiTracingRegistry.getAll();
}
function hasAITracing(name) {
  const tracing = getAITracing(name);
  if (!tracing) return false;
  const config = tracing.getConfig();
  const sampling = config.sampling;
  return sampling.type !== "never" /* NEVER */;
}
function isAITracingInstance(obj) {
  return obj instanceof MastraAITracing;
}
function setupAITracing(config) {
  const entries = Object.entries(config.instances);
  entries.forEach(([name, tracingDef], index) => {
    const instance = isAITracingInstance(tracingDef) ? tracingDef : new DefaultAITracing({ ...tracingDef, instanceName: name });
    const isDefault = index === 0;
    registerAITracing(name, instance, isDefault);
  });
  if (config.selector) {
    setAITracingSelector(config.selector);
  }
}

// src/ai-tracing/utils.ts
function sanitizeMetadata(metadata) {
  if (!metadata) return {};
  const sanitized = {};
  for (const [key, value] of Object.entries(metadata)) {
    if (isSerializable(value)) {
      sanitized[key] = value;
    }
  }
  return sanitized;
}
function isSerializable(value) {
  try {
    JSON.stringify(value);
    return true;
  } catch {
    return false;
  }
}
function omitKeys(obj, keysToOmit) {
  return Object.fromEntries(Object.entries(obj).filter(([key]) => !keysToOmit.includes(key)));
}

// src/ai-tracing/context.ts
var AGENT_GETTERS = ["getAgent", "getAgentById"];
var AGENT_METHODS_TO_WRAP = ["generate", "stream", "generateVNext", "streamVNext"];
var WORKFLOW_GETTERS = ["getWorkflow", "getWorkflowById"];
var WORKFLOW_METHODS_TO_WRAP = ["execute"];
function isNoOpSpan(span) {
  return span.constructor.name === "NoOpAISpan" || span.__isNoOp === true || !span.aiTracing;
}
function wrapMastra(mastra, tracingContext) {
  if (!tracingContext.currentSpan || isNoOpSpan(tracingContext.currentSpan)) {
    return mastra;
  }
  try {
    return new Proxy(mastra, {
      get(target, prop) {
        try {
          if (AGENT_GETTERS.includes(prop)) {
            return (...args) => {
              const agent = target[prop](...args);
              return wrapAgent(agent, tracingContext);
            };
          }
          if (WORKFLOW_GETTERS.includes(prop)) {
            return (...args) => {
              const workflow = target[prop](...args);
              return wrapWorkflow(workflow, tracingContext);
            };
          }
          return target[prop];
        } catch (error) {
          console.warn("AI Tracing: Failed to wrap method, falling back to original", error);
          return target[prop];
        }
      }
    });
  } catch (error) {
    console.warn("AI Tracing: Failed to create proxy, using original Mastra instance", error);
    return mastra;
  }
}
function wrapAgent(agent, tracingContext) {
  if (!tracingContext.currentSpan || isNoOpSpan(tracingContext.currentSpan)) {
    return agent;
  }
  try {
    return new Proxy(agent, {
      get(target, prop) {
        try {
          if (AGENT_METHODS_TO_WRAP.includes(prop)) {
            return (input, options = {}) => {
              return target[prop](input, {
                ...options,
                tracingContext
              });
            };
          }
          return target[prop];
        } catch (error) {
          console.warn("AI Tracing: Failed to wrap agent method, falling back to original", error);
          return target[prop];
        }
      }
    });
  } catch (error) {
    console.warn("AI Tracing: Failed to create agent proxy, using original instance", error);
    return agent;
  }
}
function wrapWorkflow(workflow, tracingContext) {
  if (!tracingContext.currentSpan || isNoOpSpan(tracingContext.currentSpan)) {
    return workflow;
  }
  try {
    return new Proxy(workflow, {
      get(target, prop) {
        try {
          if (WORKFLOW_METHODS_TO_WRAP.includes(prop)) {
            return (input, options = {}) => {
              return target[prop](input, {
                ...options,
                tracingContext
              });
            };
          }
          return target[prop];
        } catch (error) {
          console.warn("AI Tracing: Failed to wrap workflow method, falling back to original", error);
          return target[prop];
        }
      }
    });
  } catch (error) {
    console.warn("AI Tracing: Failed to create workflow proxy, using original instance", error);
    return workflow;
  }
}

exports.AISpanType = AISpanType;
exports.AITracingEventType = AITracingEventType;
exports.ConsoleExporter = ConsoleExporter;
exports.DefaultAITracing = DefaultAITracing;
exports.DefaultExporter = DefaultExporter;
exports.MastraAITracing = MastraAITracing;
exports.SamplingStrategyType = SamplingStrategyType;
exports.SensitiveDataFilter = SensitiveDataFilter;
exports.aiTracingDefaultConfig = aiTracingDefaultConfig;
exports.clearAITracingRegistry = clearAITracingRegistry;
exports.getAITracing = getAITracing;
exports.getAllAITracing = getAllAITracing;
exports.getDefaultAITracing = getDefaultAITracing;
exports.getSelectedAITracing = getSelectedAITracing;
exports.hasAITracing = hasAITracing;
exports.isSerializable = isSerializable;
exports.omitKeys = omitKeys;
exports.registerAITracing = registerAITracing;
exports.sanitizeMetadata = sanitizeMetadata;
exports.setAITracingSelector = setAITracingSelector;
exports.setupAITracing = setupAITracing;
exports.shutdownAITracingRegistry = shutdownAITracingRegistry;
exports.unregisterAITracing = unregisterAITracing;
exports.wrapAgent = wrapAgent;
exports.wrapMastra = wrapMastra;
exports.wrapWorkflow = wrapWorkflow;
//# sourceMappingURL=chunk-4DKPMUAC.cjs.map
//# sourceMappingURL=chunk-4DKPMUAC.cjs.map