"use strict";
/**
 * Step summarization helpers for LLM compilation context.
 *
 * Truncates and structures execution step data so the LLM receives
 * concise but structurally complete information about each step.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.truncateValue = truncateValue;
exports.truncateObject = truncateObject;
exports.summarizeSteps = summarizeSteps;
/** Truncate a value for display in the LLM prompt. */
function truncateValue(value) {
    if (Array.isArray(value)) {
        if (value.length <= 2)
            return value;
        return `[${value.length} items]`;
    }
    if (typeof value === 'string' && value.length > 200) {
        return value.slice(0, 200) + '...';
    }
    if (typeof value === 'object' && value !== null) {
        const str = JSON.stringify(value);
        if (str.length > 300)
            return str.slice(0, 300) + '...';
        return value;
    }
    return value;
}
/**
 * Truncate an object's values for LLM context, preserving structure.
 */
function truncateObject(obj, maxDepth = 2) {
    const result = {};
    for (const [key, value] of Object.entries(obj)) {
        if (Array.isArray(value)) {
            if (value.length === 0) {
                result[key] = [];
            }
            else if (value.length <= 2) {
                result[key] = value.map(v => v && typeof v === 'object' && !Array.isArray(v) && maxDepth > 1
                    ? truncateObject(v, maxDepth - 1)
                    : truncateValue(v));
            }
            else {
                // Show array structure: type, length, and first item's keys
                const firstItem = value[0];
                if (firstItem && typeof firstItem === 'object' && !Array.isArray(firstItem)) {
                    result[key] = {
                        _type: 'array',
                        _length: value.length,
                        _itemKeys: Object.keys(firstItem),
                        _firstItem: maxDepth > 1
                            ? truncateObject(firstItem, maxDepth - 1)
                            : `{${Object.keys(firstItem).join(', ')}}`,
                    };
                }
                else {
                    result[key] = { _type: 'array', _length: value.length, _itemType: typeof firstItem };
                }
            }
        }
        else if (value && typeof value === 'object' && maxDepth > 1) {
            result[key] = truncateObject(value, maxDepth - 1);
        }
        else {
            result[key] = truncateValue(value);
        }
    }
    return result;
}
/**
 * Summarize extracted steps for the LLM, including result structure.
 */
function summarizeSteps(steps) {
    // Pre-compute array outputs from all steps for provenance detection
    const arrayOutputs = [];
    for (let i = 0; i < steps.length; i++) {
        const result = steps[i].result;
        if (result && typeof result === 'object' && !Array.isArray(result)) {
            for (const [field, value] of Object.entries(result)) {
                if (Array.isArray(value) && value.length > 0) {
                    arrayOutputs.push({ stepIndex: i, field, items: value });
                }
            }
        }
    }
    return steps.map((step, index) => {
        const args = {};
        let iterationMeta = undefined;
        for (const [key, value] of Object.entries(step.arguments)) {
            if (key === '_iteration') {
                const iter = value;
                iterationMeta = {
                    tool: iter.tool,
                    count: iter.count,
                    varyingKeys: iter.varyingKeys,
                    constantArgs: iter.constantArgs,
                    arraySource: iter.arraySource,
                };
            }
            else if (Array.isArray(value) && value.length > 3) {
                // Check if this array was likely derived from a prior step's output
                let provenance = '';
                for (const ao of arrayOutputs) {
                    if (ao.stepIndex >= index)
                        continue; // only prior steps
                    if (ao.items.length > 0 && value.length > 0) {
                        const sourceValues = new Set();
                        for (const item of ao.items) {
                            if (item && typeof item === 'object') {
                                for (const v of Object.values(item)) {
                                    if (typeof v === 'string')
                                        sourceValues.add(v);
                                }
                            }
                        }
                        const targetValues = [];
                        for (const item of value) {
                            if (item && typeof item === 'object') {
                                for (const v of Object.values(item)) {
                                    if (typeof v === 'string')
                                        targetValues.push(v);
                                }
                            }
                        }
                        const overlap = targetValues.filter(v => sourceValues.has(v)).length;
                        if (overlap > value.length * 0.3) {
                            provenance = ` ⚠️ DERIVED FROM step ${ao.stepIndex} field "${ao.field}" (${overlap} overlapping values — this is NOT a user input, it was computed from step ${ao.stepIndex}'s output)`;
                            break;
                        }
                    }
                }
                args[key] = `[Array of ${value.length} items, first: ${JSON.stringify(value[0]).slice(0, 200)}]${provenance}`;
            }
            else if (typeof value === 'string' && value.length > 300) {
                args[key] = value.slice(0, 300) + '...';
            }
            else {
                args[key] = value;
            }
        }
        // Build result sample showing structure (not just keys)
        let resultSample = null;
        if (step.result && typeof step.result === 'object') {
            if (Array.isArray(step.result)) {
                resultSample = {
                    _type: 'array',
                    _length: step.result.length,
                    _firstItem: step.result[0] && typeof step.result[0] === 'object'
                        ? truncateObject(step.result[0])
                        : step.result[0],
                };
            }
            else {
                resultSample = truncateObject(step.result);
            }
        }
        const resultKeys = step.result && typeof step.result === 'object' && !Array.isArray(step.result)
            ? Object.keys(step.result)
            : [];
        return {
            index,
            kind: step.kind,
            toolName: step.toolName,
            server: step.mcpServerId,
            argumentKeys: Object.keys(step.arguments).filter(k => k !== '_iteration'),
            arguments: args,
            resultKeys,
            resultSample,
            ...(iterationMeta ? { iterationMeta } : {}),
        };
    });
}
