import {
  __spreadProps,
  __spreadValues,
  autoconvertTypedValues,
  captureError,
  collectorRESTParamsSchema,
  convertFromVercelAIMessages,
  reservedSpanParamsSchema,
  reservedTraceMetadataSchema,
  spanSchema
} from "./chunk-FWBCQQYZ.mjs";

// src/index.ts
import EventEmitter from "eventemitter3";
import { nanoid } from "nanoid";
import { ZodError } from "zod";
import { fromZodError } from "zod-validation-error";

// package.json
var version = "0.1.7";

// src/evaluations.ts
var evaluate = async (params) => {
  const slug = "slug" in params ? params.slug : params.evaluator;
  const span = optionalCreateSpan({
    trace: params.trace,
    span: params.span,
    name: params.name ? params.name : slug,
    type: params.asGuardrail ? "guardrail" : "evaluation"
  });
  try {
    const requestParams = prepareData(__spreadProps(__spreadValues({}, params), {
      slug,
      traceId: span == null ? void 0 : span.trace.traceId,
      spanId: span == null ? void 0 : span.spanId,
      span
    }));
    const response = await fetch(requestParams.url, {
      method: "POST",
      headers: requestParams.headers,
      body: JSON.stringify(requestParams.json)
    });
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    const result = await response.json();
    return handleResponse(result, span, params.asGuardrail);
  } catch (e) {
    return handleException(e, span, params.asGuardrail);
  }
};
var optionalCreateSpan = ({
  trace,
  span,
  name,
  type
}) => {
  if (span) {
    return span.startSpan({ name, type });
  } else if (trace) {
    return trace.startSpan({ name, type });
  }
  return void 0;
};
var prepareData = (params) => {
  var _a;
  const data = {};
  if (params.input) data.input = params.input;
  if (params.output) data.output = params.output;
  if (params.expectedOutput) data.expected_output = params.expectedOutput;
  if (params.contexts && params.contexts.length > 0)
    data.contexts = params.contexts;
  if (params.conversation && params.conversation.length > 0)
    data.conversation = params.conversation;
  if (params.span) {
    params.span.update({
      input: { type: "json", value: data },
      params: params.settings
    });
  }
  return {
    url: `${process.env.LANGWATCH_ENDPOINT}/api/evaluations/${params.slug}/evaluate`,
    json: {
      trace_id: params.traceId,
      span_id: params.spanId,
      name: params.name,
      data,
      settings: params.settings,
      as_guardrail: params.asGuardrail
    },
    headers: {
      "X-Auth-Token": (_a = process.env.LANGWATCH_API_KEY) != null ? _a : "",
      "Content-Type": "application/json"
    }
  };
};
var handleResponse = (response, span, asGuardrail = false) => {
  var _a;
  if (response.status === "error") {
    response.details = (_a = response.details) != null ? _a : "";
  }
  for (const key of Object.keys(response)) {
    if (response[key] === null || response[key] === void 0) {
      delete response[key];
    }
  }
  if (span) {
    const output = asGuardrail ? {
      type: "guardrail_result",
      value: response
    } : {
      type: "evaluation_result",
      value: response
    };
    span.update({ output });
    if (response.cost) {
      span.update({
        metrics: {
          cost: response.cost.amount
        }
      });
    }
    span.end();
  }
  return response;
};
var handleException = (e, span, asGuardrail = false) => {
  const response = {
    status: "error",
    details: e.toString()
  };
  if (asGuardrail) {
    response.passed = true;
  }
  return handleResponse(response, span, asGuardrail);
};

// src/langchain.ts
import { BaseCallbackHandler } from "@langchain/core/callbacks/base";
import {
  AIMessage,
  AIMessageChunk,
  FunctionMessage,
  FunctionMessageChunk,
  HumanMessage,
  HumanMessageChunk,
  SystemMessage,
  SystemMessageChunk,
  ToolMessage,
  ToolMessageChunk,
  mapChatMessagesToStoredMessages
} from "@langchain/core/messages";
import { stringify } from "javascript-stringify";
var LangWatchCallbackHandler = class extends BaseCallbackHandler {
  constructor({ trace }) {
    super();
    this.name = "LangWatchCallbackHandler";
    this.spans = {};
    this.trace = trace;
  }
  async handleLLMStart(llm, prompts, runId, parentRunId, extraParams, _tags, metadata, name) {
    this.spans[runId] = this.buildLLMSpan({
      llm,
      runId,
      parentRunId,
      input: {
        type: "json",
        value: prompts
      },
      extraParams,
      metadata,
      name
    });
  }
  buildLLMSpan({
    llm,
    runId,
    parentRunId,
    input,
    extraParams,
    metadata,
    name
  }) {
    var _a, _b, _c, _d, _e, _f, _g, _h, _i;
    try {
      const parent = this.getParent(parentRunId);
      const vendor = (_b = metadata == null ? void 0 : metadata.ls_provider) != null ? _b : (_a = llm.id.at(-2)) == null ? void 0 : _a.toString();
      const model = (_e = (_d = metadata == null ? void 0 : metadata.ls_model_name) != null ? _d : (_c = llm.kwargs) == null ? void 0 : _c.model) != null ? _e : "unknown";
      const span = parent.startLLMSpan({
        spanId: runId,
        name: name != null ? name : (_f = llm.id.at(-1)) == null ? void 0 : _f.toString(),
        input,
        model: [vendor, model].filter((x) => x).join("/"),
        params: __spreadValues({
          temperature: (_g = extraParams == null ? void 0 : extraParams.invocation_params) == null ? void 0 : _g.temperature
        }, ((_h = extraParams == null ? void 0 : extraParams.invocation_params) == null ? void 0 : _h.functions) ? { functions: (_i = extraParams == null ? void 0 : extraParams.invocation_params) == null ? void 0 : _i.functions } : {})
      });
      return span;
    } catch (e) {
      this.trace.client.emit("error", e);
      throw e;
    }
  }
  async handleChatModelStart(llm, messages, runId, parentRunId, extraParams, tags, metadata, name) {
    this.spans[runId] = this.buildLLMSpan({
      name,
      llm,
      runId,
      parentRunId,
      input: {
        type: "chat_messages",
        value: messages.flatMap(convertFromLangChainMessages)
      },
      extraParams,
      metadata
    });
  }
  async handleNewToken(_token, runId) {
    const span = this.spans[runId];
    if (runId && span && !span.timestamps.firstTokenAt) {
      span.update({
        timestamps: __spreadProps(__spreadValues({}, span.timestamps), { firstTokenAt: Date.now() })
      });
    }
  }
  async handleLLMEnd(response, runId, _parentRunId) {
    try {
      const span = this.spans[runId];
      if (!span) {
        return;
      }
      const outputs = [];
      for (const generation of response.generations) {
        for (const generation_ of generation) {
          if ("message" in generation_) {
            outputs.push({
              type: "chat_messages",
              value: convertFromLangChainMessages([
                generation_.message
              ])
            });
          } else if ("text" in generation_) {
            outputs.push({
              type: "text",
              value: generation_.text
            });
          } else {
            outputs.push({
              type: "text",
              value: JSON.stringify(generation_)
            });
          }
        }
      }
      const output = outputs.length === 1 ? outputs[0] : { type: "list", value: outputs };
      span.end({
        output
        // ...(metrics ? { metrics } : {}),
      });
    } catch (e) {
      this.trace.client.emit("error", e);
      throw e;
    }
  }
  async handleLLMError(err, runId, _parentRunId) {
    this.errorSpan({ runId, error: err });
  }
  async handleChainStart(chain, inputs, runId, parentRunId, _tags, _metadata, _runType, name) {
    this.spans[runId] = this.buildSpan({
      type: "chain",
      serialized: chain,
      runId,
      parentRunId,
      input: inputs,
      name
    });
  }
  async handleChainEnd(output, runId, _parentRunId) {
    this.endSpan({
      runId,
      output
    });
  }
  async handleChainError(err, runId, _parentRunId, _tags, _kwargs) {
    this.errorSpan({ runId, error: err });
  }
  async handleToolStart(tool, input, runId, parentRunId, _tags, _metadata, name) {
    this.spans[runId] = this.buildSpan({
      type: "tool",
      serialized: tool,
      runId,
      parentRunId,
      input,
      name
    });
  }
  async handleToolEnd(output, runId, _parentRunId) {
    this.endSpan({ runId, output });
  }
  async handleToolError(err, runId, _parentRunId, _tags) {
    this.errorSpan({ runId, error: err });
  }
  async handleRetrieverStart(retriever, query, runId, parentRunId, _tags, _metadata, name) {
    var _a, _b;
    try {
      const parent = this.getParent(parentRunId);
      this.spans[runId] = parent.startRAGSpan({
        spanId: runId,
        name: (_b = name != null ? name : retriever.name) != null ? _b : (_a = retriever.id.at(-1)) == null ? void 0 : _a.toString(),
        input: this.autoconvertTypedValues(query)
      });
    } catch (e) {
      this.trace.client.emit("error", e);
      throw e;
    }
  }
  async handleRetrieverEnd(documents, runId, _parentRunId, _tags) {
    try {
      const contexts = documents.map((doc) => __spreadValues({
        content: doc.pageContent
      }, doc.metadata.source ? { documentId: doc.metadata.source } : {}));
      const span = this.spans[runId];
      if (!span) {
        return;
      }
      span.end({
        contexts,
        output: this.autoconvertTypedValues(documents)
      });
    } catch (e) {
      this.trace.client.emit("error", e);
      throw e;
    }
  }
  async handleRetrieverError(err, runId, _parentRunId, _tags) {
    this.errorSpan({ runId, error: err });
  }
  async handleAgentAction(_action, runId, _parentRunId, _tags) {
    const span = this.spans[runId];
    if (!span) {
      return;
    }
    span.update({
      type: "agent"
    });
  }
  async handleAgentEnd(action, runId, _parentRunId, _tags) {
    this.endSpan({
      runId,
      output: action.returnValues
    });
  }
  buildSpan({
    type,
    serialized,
    runId,
    parentRunId,
    input,
    name
  }) {
    var _a, _b;
    try {
      const parent = this.getParent(parentRunId);
      const span = parent.startSpan({
        spanId: runId,
        type,
        name: (_b = name != null ? name : serialized.name) != null ? _b : (_a = serialized.id.at(-1)) == null ? void 0 : _a.toString(),
        input: this.autoconvertTypedValues(input)
      });
      return span;
    } catch (e) {
      this.trace.client.emit("error", e);
      throw e;
    }
  }
  endSpan({ runId, output }) {
    try {
      const span = this.spans[runId];
      if (!span) {
        return;
      }
      span.end({
        output: this.autoconvertTypedValues(output)
      });
    } catch (e) {
      this.trace.client.emit("error", e);
      throw e;
    }
  }
  errorSpan({ runId, error }) {
    const span = this.spans[runId];
    if (!span) {
      return;
    }
    span.end({
      error
    });
  }
  autoconvertTypedValues(value) {
    var _a;
    if (!value || typeof value === "object" && Object.keys(value).length === 0) {
      return void 0;
    }
    if (typeof value === "string") {
      return { type: "text", value };
    }
    try {
      JSON.stringify(value);
      return { type: "json", value };
    } catch (e) {
      return { type: "text", value: (_a = stringify(value)) != null ? _a : value.toString() };
    }
  }
  getParent(parentRunId) {
    var _a, _b;
    return (_b = parentRunId ? this.spans[parentRunId] : this.spans[(_a = Object.keys(this.spans).at(-1)) != null ? _a : ""]) != null ? _b : this.trace;
  }
};
var convertFromLangChainMessages = (messages) => {
  const chatMessages = [];
  for (const message of messages) {
    chatMessages.push(convertFromLangChainMessage(message));
  }
  return chatMessages;
};
var convertFromLangChainMessage = (message) => {
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
  let role = "user";
  const message_ = message.lc_serializable ? mapChatMessagesToStoredMessages([message])[0] : message;
  if (message_ instanceof HumanMessage || message_ instanceof HumanMessageChunk || ((_a = message_.id) == null ? void 0 : _a.at(-1)) === "HumanMessage" || ((_b = message_.id) == null ? void 0 : _b.at(-1)) === "HumanMessageChunk" || message_.type === "human") {
    role = "user";
  } else if (message instanceof AIMessage || message instanceof AIMessageChunk || ((_c = message.id) == null ? void 0 : _c.at(-1)) === "AIMessage" || ((_d = message.id) == null ? void 0 : _d.at(-1)) === "AIMessageChunk" || message_.type === "ai") {
    role = "assistant";
  } else if (message instanceof SystemMessage || message instanceof SystemMessageChunk || ((_e = message.id) == null ? void 0 : _e.at(-1)) === "SystemMessage" || ((_f = message.id) == null ? void 0 : _f.at(-1)) === "SystemMessageChunk" || message_.type === "system") {
    role = "system";
  } else if (message instanceof FunctionMessage || message instanceof FunctionMessageChunk || ((_g = message.id) == null ? void 0 : _g.at(-1)) === "FunctionMessage" || ((_h = message.id) == null ? void 0 : _h.at(-1)) === "FunctionMessageChunk" || message_.type === "function") {
    role = "function";
  } else if (message instanceof ToolMessage || message instanceof ToolMessageChunk || ((_i = message.id) == null ? void 0 : _i.at(-1)) === "ToolMessage" || ((_j = message.id) == null ? void 0 : _j.at(-1)) === "ToolMessageChunk" || message_.type === "tool") {
    role = "tool";
  }
  const content = typeof message.content === "string" ? message.content : message.content.map(
    (content2) => content2.type === "text" ? { type: "text", text: content2.text } : content2.type == "image_url" ? { type: "image_url", image_url: content2.image_url } : { type: "text", text: JSON.stringify(content2) }
  );
  const functionCall = message.additional_kwargs;
  return __spreadValues({
    role,
    content
  }, functionCall && typeof functionCall === "object" && Object.keys(functionCall).length > 0 ? { function_call: functionCall } : {});
};

// src/typeUtils.ts
function camelToSnakeCase(str) {
  return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
}
function camelToSnakeCaseNested(obj, parentKey) {
  if (Array.isArray(obj)) {
    return obj.map(
      (item) => camelToSnakeCaseNested(item, parentKey)
    );
  } else if (typeof obj === "object" && obj !== null) {
    const newObj = {};
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        const newKey = camelToSnakeCase(key);
        if (parentKey === "metadata" && !Object.keys(reservedTraceMetadataSchema.shape).includes(newKey) || parentKey === "params" && !Object.keys(reservedSpanParamsSchema.shape).includes(newKey) || parentKey === "input" && ["json", "raw", "list"].includes(newObj.type) && newKey === "value" || parentKey === "output" && ["json", "raw", "list"].includes(newObj.type) && newKey === "value" || parentKey === "contexts" && newKey === "content") {
          newObj[key] = obj[key];
        } else {
          newObj[newKey] = camelToSnakeCaseNested(obj[key], newKey);
        }
      }
    }
    return newObj;
  } else {
    return obj;
  }
}

// src/LangWatchExporter.ts
import { createExportTraceServiceRequest } from "@opentelemetry/otlp-transformer";

// node_modules/@opentelemetry/core/build/esm/ExportResult.js
var ExportResultCode;
(function(ExportResultCode2) {
  ExportResultCode2[ExportResultCode2["SUCCESS"] = 0] = "SUCCESS";
  ExportResultCode2[ExportResultCode2["FAILED"] = 1] = "FAILED";
})(ExportResultCode || (ExportResultCode = {}));

// src/LangWatchExporter.ts
var LangWatchExporter = class {
  constructor(params = {}) {
    var _a, _b, _c, _d, _e, _f;
    this.endpoint = (_b = (_a = params.endpoint) != null ? _a : process.env.LANGWATCH_ENDPOINT) != null ? _b : "https://app.langwatch.ai";
    this.apiKey = (_d = (_c = params.apiKey) != null ? _c : process.env.LANGWATCH_API_KEY) != null ? _d : "";
    this.includeAllSpans = (_e = params.includeAllSpans) != null ? _e : false;
    this.debug = (_f = params.debug) != null ? _f : false;
    if (!this.apiKey) {
      throw new Error("LANGWATCH_API_KEY is not set");
    }
  }
  export(allSpans, resultCallback) {
    const spans = allSpans.filter(
      (span) => this.includeAllSpans || this.isAiSdkSpan(span)
    );
    if (spans.length === 0) {
      resultCallback({ code: ExportResultCode.SUCCESS });
      return;
    }
    if (this.debug) {
      console.log("[LangWatchExporter] Exporting spans:", spans);
    }
    let body;
    try {
      body = JSON.stringify(createExportTraceServiceRequest(spans));
    } catch (error) {
      console.error("[LangWatchExporter] Failed to serialize spans:", error);
      resultCallback({ code: ExportResultCode.FAILED });
      return;
    }
    fetch(`${this.endpoint}/api/otel/v1/traces`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${this.apiKey}`
      },
      body
    }).then((response) => {
      if (!response.ok) {
        resultCallback({ code: ExportResultCode.FAILED });
        return;
      }
      resultCallback({ code: ExportResultCode.SUCCESS });
    }).catch((error) => {
      console.error("[LangWatchExporter] Failed to export spans:", error);
      resultCallback({
        code: ExportResultCode.FAILED,
        error: error instanceof Error ? error : new Error("Unknown error")
      });
    });
  }
  isAiSdkSpan(span) {
    return span.instrumentationLibrary.name === "ai";
  }
  shutdown() {
    return Promise.resolve();
  }
};

// src/index.ts
var LangWatch = class extends EventEmitter {
  constructor({
    apiKey,
    endpoint = ((_a) => (_a = process.env.LANGWATCH_ENDPOINT) != null ? _a : "https://app.langwatch.ai")()
  } = {}) {
    super();
    const apiKey_ = apiKey != null ? apiKey : process.env.LANGWATCH_API_KEY;
    if (!apiKey_) {
      const error = new Error(
        "LangWatch API key is not set, please set the LANGWATCH_API_KEY environment variable or pass it in the constructor. Traces will not be captured."
      );
      this.emit("error", error);
    }
    this.apiKey = apiKey_;
    this.endpoint = endpoint;
  }
  getTrace({
    traceId,
    metadata
  } = {}) {
    return new LangWatchTrace({
      client: this,
      traceId: traceId != null ? traceId : `trace_${nanoid()}`,
      metadata
    });
  }
  async sendTrace(params) {
    const backoff = [1e3, 2e3, 4e3, 8e3, 16e3];
    for (const backoffTime of backoff) {
      try {
        await this._sendTrace(params);
        return;
      } catch (e) {
        console.warn(
          `[LangWatch] \u26A0\uFE0F Failed to send trace, retrying in ${backoffTime / 1e3}s`
        );
        await new Promise((resolve) => setTimeout(resolve, backoffTime));
      }
    }
    console.warn("[LangWatch] \u26A0\uFE0F Failed to send trace, giving up");
  }
  async _sendTrace(params) {
    if (params.spans.length === 0) {
      return;
    }
    if (!this.apiKey) {
      const error = new Error(
        "LangWatch API key is not set, LLMs traces will not be sent, go to https://langwatch.ai to set it up"
      );
      this.emit("error", error);
      return;
    }
    const response = await fetch(`${this.endpoint}/api/collector`, {
      method: "POST",
      headers: {
        "X-Auth-Token": this.apiKey,
        "Content-Type": "application/json"
      },
      body: JSON.stringify(params)
    });
    if (response.status === 429) {
      const error = new Error(
        "Rate limit exceeded, dropping message from being sent to LangWatch. Please check your dashboard to upgrade your plan."
      );
      this.emit("error", error);
      return;
    }
    if (!response.ok) {
      const error = new Error(
        `Failed to send trace, status: ${response.status}`
      );
      this.emit("error", error);
      throw error;
    }
  }
};
var LangWatchTrace = class {
  constructor({
    client,
    traceId,
    metadata
  }) {
    this.finishedSpans = {};
    this.evaluations = [];
    this.addEvaluation = ({
      evaluationId,
      span,
      name,
      type,
      isGuardrail,
      status = "processed",
      passed,
      score,
      label,
      details,
      error,
      timestamps
    }) => {
      var _a, _b;
      const currentEvaluationIndex = this.evaluations.findIndex(
        (e) => evaluationId && "evaluationId" in e && e.evaluationId === evaluationId
      );
      const currentEvaluation = currentEvaluationIndex !== -1 ? this.evaluations[currentEvaluationIndex] : void 0;
      const evaluationResult = __spreadValues(__spreadValues(__spreadValues(__spreadValues({
        status
      }, passed !== void 0 && { passed }), score !== void 0 && { score }), label !== void 0 && { label }), details !== void 0 && { details });
      let span_ = span;
      if (!span_) {
        span_ = this.startSpan({
          type: "evaluation"
        });
      }
      if (span_.type !== "evaluation") {
        span_ = span_.startSpan({ type: "evaluation" });
      }
      span_.update({
        name,
        output: {
          type: "evaluation_result",
          value: evaluationResult
        },
        error,
        timestamps: timestamps ? {
          startedAt: (_a = timestamps.startedAt) != null ? _a : span_.timestamps.startedAt,
          finishedAt: (_b = timestamps.finishedAt) != null ? _b : void 0
        } : void 0
      });
      span_.end();
      const evaluation = {
        evaluationId: evaluationId != null ? evaluationId : `eval_${nanoid()}`,
        spanId: span_.spanId,
        name,
        type,
        isGuardrail,
        status,
        passed,
        score,
        label,
        details,
        error: error ? captureError(error) : void 0,
        timestamps: timestamps != null ? timestamps : {
          startedAt: span_.timestamps.startedAt,
          finishedAt: span_.timestamps.finishedAt
        }
      };
      if (currentEvaluation && currentEvaluationIndex !== -1) {
        this.evaluations[currentEvaluationIndex] = __spreadValues(__spreadValues({}, currentEvaluation), evaluation);
      } else {
        this.evaluations.push(evaluation);
      }
    };
    this.client = client;
    this.traceId = traceId;
    this.metadata = __spreadProps(__spreadValues({}, metadata), {
      sdkVersion: version,
      sdkLanguage: "typescript"
    });
  }
  update({ metadata }) {
    var _a, _b, _c;
    this.metadata = __spreadValues(__spreadValues(__spreadValues({}, this.metadata), metadata), typeof metadata.labels !== "undefined" ? {
      labels: [
        ...(_b = (_a = this.metadata) == null ? void 0 : _a.labels) != null ? _b : [],
        ...(_c = metadata.labels) != null ? _c : []
      ]
    } : {});
  }
  setCurrentSpan(span) {
    this.currentSpan = {
      current: span,
      previous: this.currentSpan
    };
  }
  getCurrentSpan() {
    var _a;
    return (_a = this.currentSpan) == null ? void 0 : _a.current;
  }
  resetCurrentSpan() {
    var _a;
    this.currentSpan = (_a = this.currentSpan) == null ? void 0 : _a.previous;
  }
  startSpan(params) {
    const span = new LangWatchSpan(__spreadValues({
      trace: this
    }, params));
    this.setCurrentSpan(span);
    return span;
  }
  startLLMSpan(params) {
    const span = new LangWatchLLMSpan(__spreadValues({
      trace: this
    }, params));
    this.setCurrentSpan(span);
    return span;
  }
  startRAGSpan(params) {
    const span = new LangWatchRAGSpan(__spreadValues({
      trace: this
    }, params));
    this.setCurrentSpan(span);
    return span;
  }
  async evaluate(params) {
    return evaluate(__spreadValues({
      trace: this
    }, params));
  }
  getLangChainCallback() {
    if (!this.langchainCallback) {
      this.langchainCallback = new LangWatchCallbackHandler({ trace: this });
    }
    return this.langchainCallback;
  }
  onEnd(span) {
    this.finishedSpans[span.span_id] = span;
    this.resetCurrentSpan();
    this.delayedSendSpans();
  }
  delayedSendSpans() {
    clearTimeout(this.timeoutRef);
    this.timeoutRef = setTimeout(() => {
      void this.sendSpans();
    }, 1e3);
  }
  async sendSpans() {
    clearTimeout(this.timeoutRef);
    let trace = void 0;
    try {
      trace = collectorRESTParamsSchema.parse({
        trace_id: this.traceId,
        metadata: camelToSnakeCaseNested(this.metadata, "metadata"),
        spans: Object.values(this.finishedSpans),
        evaluations: camelToSnakeCaseNested(this.evaluations)
      });
    } catch (error) {
      if (error instanceof ZodError) {
        console.warn("[LangWatch] \u26A0\uFE0F Failed to parse trace");
        console.warn(fromZodError(error).message);
      }
      this.client.emit("error", error);
    }
    if (trace) {
      await this.client.sendTrace(trace);
    }
  }
};
var LangWatchSpan = class _LangWatchSpan {
  constructor({
    trace,
    spanId,
    parentId,
    type,
    name,
    input,
    output,
    error,
    timestamps,
    metrics
  }) {
    this.spanId = spanId != null ? spanId : `span_${nanoid()}`;
    this.parentId = parentId;
    this.trace = trace;
    this.type = type != null ? type : "span";
    this.name = name;
    this.input = input;
    this.output = output;
    this.error = error;
    this.timestamps = timestamps != null ? timestamps : {
      startedAt: Date.now()
    };
    this.metrics = metrics;
  }
  update(params) {
    if (Object.isFrozen(this)) {
      const error = new Error(
        `Tried to update span ${this.spanId}, but the span is already finished, discarding update`
      );
      this.trace.client.emit("error", error);
      return;
    }
    if (params.type) {
      this.type = params.type;
    }
    if ("name" in params) {
      this.name = params.name;
    }
    if ("input" in params) {
      this.input = params.input;
    }
    if ("output" in params) {
      this.output = params.output;
    }
    if ("error" in params) {
      this.error = params.error;
    }
    if (params.timestamps) {
      this.timestamps = params.timestamps;
    }
    if ("metrics" in params) {
      this.metrics = params.metrics;
    }
  }
  startSpan(params) {
    const span = new _LangWatchSpan(__spreadValues({
      trace: this.trace,
      parentId: this.spanId
    }, params));
    this.trace.setCurrentSpan(span);
    return span;
  }
  startLLMSpan(params) {
    const span = new LangWatchLLMSpan(__spreadValues({
      trace: this.trace,
      parentId: this.spanId
    }, params));
    this.trace.setCurrentSpan(span);
    return span;
  }
  startRAGSpan(params) {
    const span = new LangWatchRAGSpan(__spreadValues({
      trace: this.trace,
      parentId: this.spanId
    }, params));
    this.trace.setCurrentSpan(span);
    return span;
  }
  addEvaluation(params) {
    this.trace.addEvaluation(__spreadProps(__spreadValues({}, params), {
      span: this
    }));
  }
  async evaluate(params) {
    return evaluate(__spreadValues({
      span: this
    }, params));
  }
  end(params) {
    this.timestamps.finishedAt = Date.now();
    if (params) {
      this.update(params);
    }
    try {
      const finalSpan = spanSchema.parse(
        camelToSnakeCaseNested(__spreadValues(__spreadProps(__spreadValues({}, this), {
          trace: void 0,
          traceId: this.trace.traceId,
          timestamps: __spreadProps(__spreadValues({}, this.timestamps), {
            finishedAt: this.timestamps.finishedAt
          })
        }), this.error && { error: captureError(this.error) }))
      );
      this.trace.onEnd(finalSpan);
    } catch (error) {
      if (error instanceof ZodError) {
        console.warn("[LangWatch] \u26A0\uFE0F Failed to parse span");
        console.warn(fromZodError(error).message);
      }
      this.trace.client.emit("error", error);
    }
  }
};
var LangWatchLLMSpan = class extends LangWatchSpan {
  constructor(params) {
    var _a, _b;
    super(__spreadValues({}, params));
    this.type = "llm";
    this.model = (_a = params.model) != null ? _a : "unknown";
    this.params = (_b = params.params) != null ? _b : {};
  }
  update(params) {
    super.update(params);
    if (params.model) {
      this.model = params.model;
    }
    if (params.params) {
      this.params = params.params;
    }
  }
  end(params) {
    super.end(params);
  }
};
var LangWatchRAGSpan = class extends LangWatchSpan {
  constructor(params) {
    var _a;
    super(__spreadValues({}, params));
    this.type = "rag";
    this.contexts = (_a = params.contexts) != null ? _a : [];
  }
  update(params) {
    super.update(params);
    if (params.contexts) {
      this.contexts = params.contexts;
    }
  }
  end(params) {
    super.end(params);
  }
};
export {
  LangWatch,
  LangWatchExporter,
  LangWatchLLMSpan,
  LangWatchRAGSpan,
  LangWatchSpan,
  LangWatchTrace,
  autoconvertTypedValues,
  captureError,
  convertFromVercelAIMessages
};
//# sourceMappingURL=index.mjs.map