"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GenericParser = void 0;
const spanDeduplicator_1 = require("../utils/spanDeduplicator");
const toolCallAnalyzer_1 = require("../utils/toolCallAnalyzer");
const utilts_1 = require("../utils/utilts");
/**
 * Generic Parser (Fallback)
 */
class GenericParser {
    constructor() {
        this.name = 'generic';
        this.deduplicator = new spanDeduplicator_1.SpanDeduplicator();
        this.toolAnalyzer = new toolCallAnalyzer_1.ToolCallAnalyzer();
    }
    canParse(_spans) {
        return true; // Always can parse as fallback
    }
    getTools(spans) {
        this.deduplicator.reset();
        return spans
            .filter(s => !this.deduplicator.isDuplicate(s))
            .filter(s => s.name.includes('tool') || s.attributes['genai.tool.name'])
            .map(s => (0, utilts_1.buildCanonicalTool)({
            id: s.id,
            name: this.toolAnalyzer.extractToolName(s) || s.name,
            input: s.attributes['genai.workflow.input'],
            output: s.attributes['genai.workflow.output'],
            duration: s.duration,
            timestamp: s.timestamp,
            spanId: s.id,
            executionType: 'actual',
            metadata: { spanId: s.id },
        }));
    }
    getAgents(spans) {
        this.deduplicator.reset();
        return spans
            .filter(s => !this.deduplicator.isDuplicate(s))
            .filter(s => s.name.includes('agent'))
            .map(s => (0, utilts_1.buildCanonicalAgent)({
            id: s.id,
            name: s.name,
            type: 'generic',
            metadata: { spanId: s.id, timestamp: s.timestamp, duration: s.duration },
        }));
    }
    getModels(spans) {
        this.deduplicator.reset();
        return spans
            .filter(s => !this.deduplicator.isDuplicate(s))
            .filter(s => utilts_1.FrameworkUtils.getModelAttr(s.attributes, 'gen_ai.response.model', 'genai.response.model', 'gen_ai.request.model', 'genai.request.model'))
            .map(s => this.extractModel(s))
            .filter((m) => m !== null);
    }
    extractModel(span) {
        const attrs = span.attributes;
        const modelName = utilts_1.FrameworkUtils.getModelAttrResponseFirst(attrs);
        if (!modelName)
            return null;
        const inputTokens = utilts_1.FrameworkUtils.safeParseInt(utilts_1.FrameworkUtils.getAttr(attrs, 'gen_ai.usage.input_tokens', 'genai.usage.inputtokens'));
        const outputTokens = utilts_1.FrameworkUtils.safeParseInt(utilts_1.FrameworkUtils.getAttr(attrs, 'gen_ai.usage.output_tokens', 'genai.usage.outputtokens'));
        let totalTokens = utilts_1.FrameworkUtils.safeParseInt(utilts_1.FrameworkUtils.getAttr(attrs, 'gen_ai.usage.total_tokens', 'genai.usage.totaltokens'));
        if (!totalTokens && (inputTokens || outputTokens))
            totalTokens = inputTokens + outputTokens;
        const { cacheRead, cacheWrite } = utilts_1.FrameworkUtils.getCacheTokens(attrs);
        return (0, utilts_1.buildCanonicalExtendedModel)({
            id: span.id,
            provider: utilts_1.FrameworkUtils.getAttr(attrs, 'gen_ai.system', 'genai.system') || 'unknown',
            modelName: String(modelName),
            tokenUsage: {
                inputTokens,
                outputTokens,
                totalTokens,
                ...(cacheRead != null && { cacheRead }),
                ...(cacheWrite != null && { cacheWrite }),
            },
            spanId: span.id,
            timestamp: span.timestamp,
            temperature: utilts_1.FrameworkUtils.safeParseFloat(utilts_1.FrameworkUtils.getAttr(attrs, 'gen_ai.request.temperature', 'genai.request.temperature')),
            cost: utilts_1.FrameworkUtils.safeParseFloat(utilts_1.FrameworkUtils.getAttr(attrs, 'gen_ai.usage.cost', 'genai.usage.cost')) || 0,
            ttft: utilts_1.FrameworkUtils.safeParseFloat(attrs['gen_ai.server.time_to_first_token']),
            serverTimePerOutputToken: utilts_1.FrameworkUtils.safeParseFloat(attrs['gen_ai.server.time_per_output_token']),
            prompt: utilts_1.FrameworkUtils.getAttr(attrs, 'gen_ai.prompt', 'genai.prompt'),
            completion: utilts_1.FrameworkUtils.getAttr(attrs, 'gen_ai.completion', 'genai.completion'),
            duration: utilts_1.FrameworkUtils.safeParseFloat(span.duration ?? 0) ?? 0,
        });
    }
    generateDag(spans) {
        this.deduplicator.reset();
        const uniqueSpans = spans.filter(s => !this.deduplicator.isDuplicate(s));
        const nodeMap = new Map();
        uniqueSpans.forEach(s => {
            nodeMap.set(s.id, {
                id: s.id,
                type: 'workflow',
                name: s.name,
                children: [],
                metadata: { attributes: s.attributes }
            });
        });
        uniqueSpans.forEach(s => {
            if (s.parentSpanId && nodeMap.has(s.parentSpanId)) {
                nodeMap.get(s.parentSpanId).children.push(s.id);
            }
        });
        const nodes = Array.from(nodeMap.values());
        const byTime = [...uniqueSpans].sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
        const firstSpanId = byTime.length > 0 && nodeMap.has(byTime[0].id) ? byTime[0].id : undefined;
        const lastSpanId = byTime.length > 0 && nodeMap.has(byTime[byTime.length - 1].id)
            ? byTime[byTime.length - 1].id
            : undefined;
        if (firstSpanId != null) {
            nodes.push({
                id: 'prompt',
                type: 'prompt',
                name: 'Prompt',
                children: [firstSpanId],
                metadata: {}
            });
        }
        if (lastSpanId != null) {
            const lastNode = nodeMap.get(lastSpanId);
            if (lastNode)
                lastNode.children = [...lastNode.children, 'response'];
            nodes.push({
                id: 'response',
                type: 'response',
                name: 'Response',
                children: [],
                metadata: {}
            });
        }
        return nodes;
    }
    generateLinearFlow(spans) {
        this.deduplicator.reset();
        // Generic has no agent/tool/model classification; linear flow only contains agent/tool/model (prompt/response added at render).
        return [];
    }
}
exports.GenericParser = GenericParser;
//# sourceMappingURL=generic.js.map