{"version":3,"file":"tracer_langchain.cjs","names":["AIMessage","mergeUsageMetadata","BaseTracer","getDefaultLangChainClientSingleton","RunTree"],"sources":["../../src/tracers/tracer_langchain.ts"],"sourcesContent":["import {\n  type Client,\n  type LangSmithTracingClientInterface,\n  getDefaultProjectName,\n} from \"langsmith\";\nimport { RunTree, type RunTreeConfig } from \"langsmith/run_trees\";\nimport { getCurrentRunTree } from \"langsmith/singletons/traceable\";\n\nimport {\n  BaseRun,\n  RunCreate,\n  RunUpdate as BaseRunUpdate,\n  KVMap,\n} from \"langsmith/schemas\";\nimport { BaseTracer, Run as BaseTracerRun } from \"./base.js\";\nimport { BaseCallbackHandlerInput } from \"../callbacks/base.js\";\nimport { getDefaultLangChainClientSingleton } from \"../singletons/tracer.js\";\nimport { ChatGeneration } from \"../outputs.js\";\nimport { AIMessage } from \"../messages/ai.js\";\nimport { mergeUsageMetadata, UsageMetadata } from \"../messages/metadata.js\";\n\nexport interface Run extends BaseRun {\n  id: string;\n  child_runs: this[];\n  child_execution_order: number;\n  dotted_order?: string;\n  trace_id?: string;\n}\n\nexport interface RunCreate2 extends RunCreate {\n  trace_id?: string;\n  dotted_order?: string;\n}\n\nexport interface RunUpdate extends BaseRunUpdate {\n  events: BaseRun[\"events\"];\n  inputs: KVMap;\n  trace_id?: string;\n  dotted_order?: string;\n}\n\nexport interface LangChainTracerFields extends BaseCallbackHandlerInput {\n  exampleId?: string;\n  projectName?: string;\n  client?: LangSmithTracingClientInterface;\n  replicas?: RunTreeConfig[\"replicas\"];\n  metadata?: Record<string, unknown>;\n  tags?: string[];\n}\n\n/**\n * Extract usage_metadata from chat generations.\n *\n * Iterates through generations to find and aggregates all usage_metadata\n * found in chat messages. This is typically present in chat model outputs.\n */\nfunction _getUsageMetadataFromGenerations(\n  generations: ChatGeneration[][]\n): UsageMetadata | undefined {\n  let output: UsageMetadata | undefined = undefined;\n  for (const generationBatch of generations) {\n    for (const generation of generationBatch) {\n      if (\n        AIMessage.isInstance(generation.message) &&\n        generation.message.usage_metadata !== undefined\n      ) {\n        output = mergeUsageMetadata(output, generation.message.usage_metadata);\n      }\n    }\n  }\n  return output;\n}\n\nexport class LangChainTracer\n  extends BaseTracer\n  implements LangChainTracerFields\n{\n  name = \"langchain_tracer\";\n\n  projectName?: string;\n\n  exampleId?: string;\n\n  client: LangSmithTracingClientInterface;\n\n  replicas?: RunTreeConfig[\"replicas\"];\n\n  usesRunTreeMap = true;\n\n  tracingMetadata?: Record<string, unknown>;\n\n  tracingTags: string[] = [];\n\n  constructor(protected fields: LangChainTracerFields = {}) {\n    super(fields);\n    const { exampleId, projectName, client, replicas, metadata, tags } = fields;\n\n    this.projectName = projectName ?? getDefaultProjectName();\n    this.replicas = replicas;\n    this.exampleId = exampleId;\n    this.client = client ?? getDefaultLangChainClientSingleton();\n    this.tracingMetadata = metadata ? { ...metadata } : undefined;\n    this.tracingTags = tags ?? [];\n\n    const traceableTree = LangChainTracer.getTraceableRunTree();\n    if (traceableTree) {\n      this.updateFromRunTree(traceableTree);\n    }\n  }\n\n  protected async persistRun(_run: Run): Promise<void> {\n    // empty\n  }\n\n  async onRunCreate(run: Run): Promise<void> {\n    _patchMissingTracingDefaults(this, run);\n    if (!run.extra?.lc_defers_inputs) {\n      const runTree = this.getRunTreeWithTracingConfig(run.id);\n      await runTree?.postRun();\n    }\n  }\n\n  async onRunUpdate(run: Run): Promise<void> {\n    _patchMissingTracingDefaults(this, run);\n    const runTree = this.getRunTreeWithTracingConfig(run.id);\n    if (run.extra?.lc_defers_inputs) {\n      await runTree?.postRun();\n    } else {\n      await runTree?.patchRun();\n    }\n  }\n\n  onLLMEnd(run: BaseTracerRun): void {\n    // Extract usage_metadata from outputs and store in extra.metadata\n    const outputs = run.outputs as\n      | { generations?: ChatGeneration[][] }\n      | undefined;\n    if (outputs?.generations) {\n      const usageMetadata = _getUsageMetadataFromGenerations(\n        outputs.generations\n      );\n      if (usageMetadata !== undefined) {\n        run.extra = run.extra ?? {};\n        const metadata =\n          (run.extra.metadata as Record<string, unknown> | undefined) ?? {};\n        metadata.usage_metadata = usageMetadata;\n        run.extra.metadata = metadata;\n      }\n    }\n  }\n\n  copyWithTracingConfig({\n    metadata,\n    tags,\n  }: {\n    metadata?: Record<string, unknown>;\n    tags?: string[];\n  }): LangChainTracer {\n    let mergedMetadata: Record<string, unknown> | undefined;\n    if (metadata === undefined) {\n      mergedMetadata = this.tracingMetadata\n        ? { ...this.tracingMetadata }\n        : undefined;\n    } else if (this.tracingMetadata === undefined) {\n      mergedMetadata = { ...metadata };\n    } else {\n      mergedMetadata = { ...this.tracingMetadata };\n      for (const [key, value] of Object.entries(metadata)) {\n        if (!Object.prototype.hasOwnProperty.call(mergedMetadata, key)) {\n          mergedMetadata[key] = value;\n        }\n      }\n    }\n\n    const mergedTags = tags\n      ? Array.from(new Set([...this.tracingTags, ...tags]))\n      : [...this.tracingTags];\n\n    const copied = new LangChainTracer({\n      ...this.fields,\n      metadata: mergedMetadata,\n      tags: mergedTags,\n    });\n    copied.runMap = this.runMap;\n    copied.runTreeMap = this.runTreeMap;\n    return copied;\n  }\n\n  getRun(id: string): Run | undefined {\n    return this.runTreeMap.get(id);\n  }\n\n  updateFromRunTree(runTree: RunTree) {\n    this.runTreeMap.set(runTree.id, runTree);\n    let rootRun: RunTree = runTree;\n    const visited = new Set<string>();\n    while (rootRun.parent_run) {\n      if (visited.has(rootRun.id)) break;\n      visited.add(rootRun.id);\n\n      if (!rootRun.parent_run) break;\n      rootRun = rootRun.parent_run as RunTree;\n    }\n    visited.clear();\n\n    const queue = [rootRun];\n    while (queue.length > 0) {\n      const current = queue.shift();\n      if (!current || visited.has(current.id)) continue;\n      visited.add(current.id);\n\n      this.runTreeMap.set(current.id, current);\n      if (current.child_runs) {\n        queue.push(...current.child_runs);\n      }\n    }\n\n    this.client = runTree.client ?? this.client;\n    this.replicas = runTree.replicas ?? this.replicas;\n    this.projectName = runTree.project_name ?? this.projectName;\n    this.exampleId = runTree.reference_example_id ?? this.exampleId;\n    this.fields = {\n      ...this.fields,\n      client: this.client,\n      replicas: this.replicas,\n      projectName: this.projectName,\n      exampleId: this.exampleId,\n    };\n  }\n\n  getRunTreeWithTracingConfig(id: string): RunTree | undefined {\n    const runTree = this.runTreeMap.get(id);\n    if (!runTree) return undefined;\n\n    return new RunTree({\n      ...runTree,\n      client: this.client as Client,\n      project_name: this.projectName,\n      replicas: this.replicas,\n      reference_example_id: this.exampleId,\n      tracingEnabled: true,\n    });\n  }\n\n  static getTraceableRunTree(): RunTree | undefined {\n    try {\n      return (\n        // The type cast here provides forward compatibility. Old versions of LangSmith will just\n        // ignore the permitAbsentRunTree arg.\n        (\n          getCurrentRunTree as (\n            permitAbsentRunTree: boolean\n          ) => ReturnType<typeof getCurrentRunTree> | undefined\n        )(true)\n      );\n    } catch {\n      return undefined;\n    }\n  }\n\n  static [Symbol.hasInstance](instance: unknown): boolean {\n    if (typeof instance !== \"object\" || instance === null) {\n      return false;\n    }\n    const candidate = instance as Record<string, unknown>;\n    return (\n      \"name\" in candidate &&\n      candidate.name === \"langchain_tracer\" &&\n      \"copyWithTracingConfig\" in candidate &&\n      typeof candidate.copyWithTracingConfig === \"function\" &&\n      \"getRunTreeWithTracingConfig\" in candidate &&\n      typeof candidate.getRunTreeWithTracingConfig === \"function\"\n    );\n  }\n}\n\nfunction _patchMissingTracingDefaults(tracer: LangChainTracer, run: Run): void {\n  if (tracer.tracingMetadata) {\n    run.extra ??= {};\n    const metadata: Record<string, unknown> =\n      (run.extra.metadata as Record<string, unknown> | undefined) ?? {};\n    let didPatchMetadata = false;\n    for (const [key, value] of Object.entries(tracer.tracingMetadata)) {\n      if (!Object.prototype.hasOwnProperty.call(metadata, key)) {\n        metadata[key] = value;\n        didPatchMetadata = true;\n      }\n    }\n    if (didPatchMetadata) {\n      run.extra.metadata = metadata;\n    }\n  }\n\n  if (tracer.tracingTags.length > 0) {\n    run.tags = Array.from(\n      new Set([...(run.tags ?? []), ...tracer.tracingTags])\n    );\n  }\n}\n"],"mappings":"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"}