"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.LangChainTracer = void 0;
const base_1 = require("@langchain/core/tracers/base");
const api_1 = require("@opentelemetry/api");
const core_1 = require("@opentelemetry/core");
const openinference_semantic_conventions_1 = require("@arizeai/openinference-semantic-conventions");
const utils_1 = require("./utils");
class LangChainTracer extends base_1.BaseTracer {
    constructor(tracer) {
        super();
        this.runs = {};
        this.name = "OpenInferenceLangChainTracer";
        this.tracer = tracer;
    }
    persistRun(_run) {
        return Promise.resolve();
    }
    /**
     * Called when a new run is created on v0.1.0 of langchain see {@link BaseTracer}
     * @param run the langchain {@link Run} object
     *
     * This method is only available on langchain ^0.1.0 BaseTracer and has been replaced in 0.2 by onRunCreate
     * we support both 0.1 and 0.2 so we need to check if the method exists on the super class before calling it
     */
    _startTrace(run) {
        const _super = Object.create(null, {
            _startTrace: { get: () => super._startTrace }
        });
        return __awaiter(this, void 0, void 0, function* () {
            // eslint-disable-next-line @typescript-eslint/ban-ts-comment
            // @ts-ignore
            if (typeof _super._startTrace === "function") {
                // eslint-disable-next-line @typescript-eslint/ban-ts-comment
                // @ts-ignore
                yield _super._startTrace.call(this, run);
            }
            yield this.startTracing(run);
        });
    }
    /**
     * Called when a new run is created on v0.2.0 of langchain see {@link BaseTracer}
     * @param run the langchain {@link Run} object
     *
     * This method is only available on the langchain ^0.2.0 {@link BaseTracer}
     */
    onRunCreate(run) {
        const _super = Object.create(null, {
            onRunCreate: { get: () => super.onRunCreate }
        });
        return __awaiter(this, void 0, void 0, function* () {
            if (typeof _super.onRunCreate === "function") {
                yield _super.onRunCreate.call(this, run);
            }
            yield this.startTracing(run);
        });
    }
    startTracing(run) {
        return __awaiter(this, void 0, void 0, function* () {
            var _a;
            if ((0, core_1.isTracingSuppressed)(api_1.context.active())) {
                return;
            }
            /**
             * If the parent span context is available, use it as the active context for the new span.
             * This will allow the new span to be a child of the parent span.
             */
            let activeContext = api_1.context.active();
            const parentCtx = this.getParentSpanContext(run);
            if (parentCtx != null) {
                activeContext = api_1.trace.setSpanContext(api_1.context.active(), parentCtx);
            }
            const span = this.tracer.startSpan(run.name, {
                kind: api_1.SpanKind.INTERNAL,
                attributes: {
                    [openinference_semantic_conventions_1.SemanticConventions.OPENINFERENCE_SPAN_KIND]: (_a = (0, utils_1.safelyGetOpenInferenceSpanKindFromRunType)(run.run_type)) !== null && _a !== void 0 ? _a : undefined,
                },
            }, activeContext);
            this.runs[run.id] = { run, span };
        });
    }
    _endTrace(run) {
        const _super = Object.create(null, {
            _endTrace: { get: () => super._endTrace }
        });
        return __awaiter(this, void 0, void 0, function* () {
            yield _super._endTrace.call(this, run);
            if ((0, core_1.isTracingSuppressed)(api_1.context.active())) {
                return;
            }
            const runWithSpan = this.runs[run.id];
            if (!runWithSpan) {
                return;
            }
            const { span } = runWithSpan;
            if (run.error != null) {
                span.setStatus({
                    code: api_1.SpanStatusCode.ERROR,
                    message: run.error,
                });
            }
            else {
                span.setStatus({ code: api_1.SpanStatusCode.OK });
            }
            const attributes = (0, utils_1.safelyFlattenAttributes)(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (0, utils_1.safelyFormatIO)({ io: run.inputs, ioType: "input" })), (0, utils_1.safelyFormatIO)({ io: run.outputs, ioType: "output" })), (0, utils_1.safelyFormatInputMessages)(run.inputs)), (0, utils_1.safelyFormatOutputMessages)(run.outputs)), (0, utils_1.safelyFormatRetrievalDocuments)(run)), (0, utils_1.safelyFormatLLMParams)(run.extra)), (0, utils_1.safelyFormatPromptTemplate)(run)), (0, utils_1.safelyFormatTokenCounts)(run.outputs)), (0, utils_1.safelyFormatFunctionCalls)(run.outputs)), (0, utils_1.safelyFormatToolCalls)(run)), (0, utils_1.safelyFormatMetadata)(run)), (0, utils_1.safelyFormatSessionId)(run)));
            if (attributes != null) {
                span.setAttributes(attributes);
            }
            runWithSpan.span.end();
            delete this.runs[run.id];
        });
    }
    getParentSpanContext(run) {
        if (run.parent_run_id == null) {
            return;
        }
        const maybeParent = this.runs[run.parent_run_id];
        if (maybeParent == null) {
            return;
        }
        return maybeParent.span.spanContext();
    }
}
exports.LangChainTracer = LangChainTracer;
//# sourceMappingURL=tracer.js.map