"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTruPulseTools = getTruPulseTools;
// Note: LangChain tools will be implemented when LangChain is installed
// For now, we'll create a simple tool interface
const fetch_1 = require("../../../../fetch");
const logger_1 = __importDefault(require("../../../../logger"));
const argusSwagger_1 = require("../../../swagger/argusSwagger");
function createTool(name, description, schema, execute) {
    return { name, description, schema, execute };
}
const envars_1 = require("../../../../envars");
/**
 * Get base URL for API calls
 * Uses environment variable or defaults to localhost with default port
 */
function getBaseUrl() {
    // Check for environment variable (using process.env directly since it's not in the typed envars)
    const apiUrl = process.env.TRUSYS_API_URL || process.env.API_BASE_URL || process.env.API_URL;
    if (apiUrl) {
        // Remove trailing slash if present
        return apiUrl.replace(/\/$/, '');
    }
    // Default to localhost with default port
    const port = (0, envars_1.getEnvInt)('API_PORT', 15500);
    return `http://localhost:${port}`;
}
/**
 * Base path for TruPulse APIs
 */
const API_PATH = '/api/argus';
/**
 * Helper to call API and handle errors
 */
async function callApi(endpoint, params) {
    try {
        // Build query string from params
        const queryParams = new URLSearchParams();
        // Add projectId and orgId if present
        if (params.projectId) {
            queryParams.append('projectId', params.projectId);
        }
        if (params.orgId) {
            queryParams.append('orgId', params.orgId);
        }
        // Extract applicationId, sessionId, traceId, spanId, includeEvaluationResults, and evalResultsFilters from filters if present
        const filters = params.filters || {};
        const applicationId = params.applicationId || filters.applicationId;
        const sessionId = params.sessionId || filters.sessionId;
        const traceId = params.traceId || filters.traceId;
        const spanId = params.spanId || filters.spanId;
        const includeEvaluationResults = params.includeEvaluationResults === undefined ? filters.includeEvaluationResults : params.includeEvaluationResults;
        const evalResultsFilters = params.evalResultsFilters || filters.evalResultsFilters;
        // Handle different parameter types
        if (params.filters || applicationId || sessionId || traceId || spanId || includeEvaluationResults !== undefined || evalResultsFilters) {
            // Ensure filters object includes all extracted values
            const finalFilters = {
                ...filters,
                ...(applicationId && { applicationId }),
                ...(sessionId && { sessionId }),
                ...(traceId && { traceId }),
                ...(spanId && { spanId }),
                ...(includeEvaluationResults !== undefined && { includeEvaluationResults }),
                ...(evalResultsFilters && { evalResultsFilters }),
            };
            queryParams.append('filters', JSON.stringify(finalFilters));
        }
        if (params.sorting) {
            queryParams.append('sorting', JSON.stringify(params.sorting));
        }
        if (params.limit !== undefined) {
            queryParams.append('limit', String(params.limit));
        }
        if (params.offset !== undefined) {
            queryParams.append('offset', String(params.offset));
        }
        if (traceId) {
            queryParams.append('traceId', traceId);
        }
        if (params.traceIds) {
            queryParams.append('traceIds', Array.isArray(params.traceIds) ? params.traceIds.join(',') : params.traceIds);
        }
        if (spanId) {
            queryParams.append('spanId', spanId);
        }
        if (params.spanIds) {
            queryParams.append('spanIds', Array.isArray(params.spanIds) ? params.spanIds.join(',') : params.spanIds);
        }
        if (params.sessionId) {
            queryParams.append('sessionId', params.sessionId);
        }
        if (params.sessionIds) {
            queryParams.append('sessionIds', Array.isArray(params.sessionIds) ? params.sessionIds.join(',') : params.sessionIds);
        }
        if (params.summaryOnly !== undefined) {
            queryParams.append('summaryOnly', String(params.summaryOnly));
        }
        // Generic extras used by various tools
        if (params.sort) {
            queryParams.append('sort', JSON.stringify(params.sort));
        }
        if (params.page !== undefined) {
            queryParams.append('page', String(params.page));
        }
        if (params.pageSize !== undefined) {
            queryParams.append('pageSize', String(params.pageSize));
        }
        if (params.entity) {
            queryParams.append('entity', String(params.entity));
        }
        if (params.id) {
            queryParams.append('id', String(params.id));
        }
        if (params.group_by) {
            queryParams.append('group_by', String(params.group_by));
        }
        if (params.evaluationId) {
            queryParams.append('evaluationId', String(params.evaluationId));
        }
        if (params.findingId) {
            queryParams.append('findingId', String(params.findingId));
        }
        if (params.timeRange) {
            queryParams.append('timeRange', typeof params.timeRange === 'string' ? params.timeRange : JSON.stringify(params.timeRange));
        }
        if (params.key) {
            queryParams.append('key', String(params.key));
        }
        if (params.prefix) {
            queryParams.append('prefix', String(params.prefix));
        }
        if (params.include) {
            queryParams.append('include', String(params.include));
        }
        if (params.eventName) {
            queryParams.append('eventName', String(params.eventName));
        }
        if (params.query) {
            queryParams.append('query', String(params.query));
        }
        const queryString = queryParams.toString();
        const baseUrl = getBaseUrl();
        const apiUrl = `${baseUrl}${API_PATH}${endpoint}${queryString ? `?${queryString}` : ''}`;
        // Use existing fetchWithRetries helper (timeout in ms, retries count)
        const response = await (0, fetch_1.fetchWithRetries)(apiUrl, {
            method: 'GET',
            headers: { 'Content-Type': 'application/json' },
        }, 30000, // 30s timeout
        3);
        const result = await response.json();
        if (!result.success) {
            throw new Error(result.message || 'API call failed');
        }
        return JSON.stringify(result.data);
    }
    catch (error) {
        logger_1.default.error(`MCP tool API call failed: ${error}`);
        return JSON.stringify({
            error: error instanceof Error ? error.message : String(error),
        });
    }
}
/**
 * Build JSON schema for a tool from the Swagger operation parameters.
 * We keep this intentionally simple and override projectId/orgId explicitly
 * so it is easy to tweak later.
 */
function buildSchemaFromSwagger(op) {
    const properties = {};
    const required = [];
    (op.parameters || []).forEach((param) => {
        // Skip $ref params (projectId/orgId) – we add them explicitly below
        if (param.$ref) {
            return;
        }
        const name = param.name;
        const schema = param.schema || {};
        const prop = {
            type: schema.type || 'string',
        };
        if (schema.enum) {
            prop.enum = schema.enum;
        }
        if (param.description) {
            prop.description = param.description;
        }
        properties[name] = prop;
        if (param.required) {
            required.push(name);
        }
    });
    // Always allow projectId / orgId to be passed from the agent
    properties.projectId = {
        type: 'string',
        description: 'Project ID (forwarded as query parameter)',
    };
    properties.orgId = {
        type: 'string',
        description: 'Organization ID (forwarded as query parameter)',
    };
    const schema = {
        type: 'object',
        properties,
    };
    if (required.length > 0) {
        schema.required = required;
    }
    return schema;
}
/**
 * Add includeEvaluationResults and evalResultsFilters to trace/span/session tool schemas
 */
function addEvalParamsToSchema(schema, path) {
    const isTraceSpanSessionTool = path.includes('/get-trace') ||
        path.includes('/search-traces') ||
        path.includes('/get-traces-by-ids') ||
        path.includes('/get-span') ||
        path.includes('/search-spans') ||
        path.includes('/get-spans-by-ids') ||
        path.includes('/get-session') ||
        path.includes('/search-sessions') ||
        path.includes('/get-sessions-by-ids');
    if (isTraceSpanSessionTool) {
        schema.properties.includeEvaluationResults = {
            type: 'boolean',
            description: 'Optional. Set to true to include evaluation results in the response. Default is false. Use this for queries about evaluations, metrics, assertions, scores, pass/fail, redteam, or security findings.',
        };
        schema.properties.evalResultsFilters = {
            type: 'object',
            description: 'Optional. Additional filters for evaluation results (e.g., { pass: false } for only failed evaluations). Only include this when user explicitly asks for filtered evaluation details. For simple queries like "Did the trace evaluation pass or fail?", use includeEvaluationResults: true without evalResultsFilters.',
        };
    }
    return schema;
}
/**
 * Convert a Swagger path like `/tools/get-traces` into a stable tool name
 * that matches what the MCP server expects (e.g. `get_traces`).
 */
function pathToToolName(path) {
    const lastSegment = path.split('/').filter(Boolean).pop() || '';
    return lastSegment.replace(/-/g, '_');
}
/**
 * Build Tool objects from the Argus Swagger spec.
 * This keeps tool names, descriptions, and schemas in sync with the API docs.
 */
function buildToolsFromSwagger() {
    const tools = [];
    Object.entries(argusSwagger_1.argusSwaggerSpec).forEach(([path, config]) => {
        // We only expose `/tools/*` GET endpoints as MCP tools
        if (!path.startsWith('/tools/')) {
            return;
        }
        const op = config.get;
        if (!op) {
            return;
        }
        const name = pathToToolName(path);
        const description = op.description ||
            op.summary ||
            `Call ${path}`;
        let schema = buildSchemaFromSwagger(op);
        schema = addEvalParamsToSchema(schema, path);
        tools.push(createTool(name, description, schema, async (input) => {
            // Delegate to the shared HTTP caller; it already knows how to
            // encode filters, sorting, pagination, etc.
            return callApi(path, input);
        }));
    });
    return tools;
}
/**
 * Get all TruPulse tools
 */
function getTruPulseTools() {
    return buildToolsFromSwagger();
}
//# sourceMappingURL=truPulseTools.js.map