"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.executeAddressMcpQuery = executeAddressMcpQuery; const config_1 = require("../config"); function toStringValue(value) { if (value === null || value === undefined) { return ""; } return String(value); } function parseFiniteNumber(value) { if (typeof value === "number" && Number.isFinite(value)) { return value; } if (typeof value === "string") { const parsed = Number(value.replace(",", ".").trim()); if (Number.isFinite(parsed)) { return parsed; } } return null; } function parseRowsFromTextTable(source) { const normalized = String(source ?? "").replace(/\r/g, "").trim(); if (!normalized) { return []; } const headerMatch = normalized.match(/\{([^}]*)\}:/); if (!headerMatch) { return []; } const columns = String(headerMatch[1] ?? "") .split(",") .map((item) => item.replace(/^"+|"+$/g, "").trim()) .filter(Boolean); const body = normalized.slice((headerMatch.index ?? 0) + headerMatch[0].length).trim(); if (!body) { return []; } const rows = []; const parseCsvLine = (line) => { const values = []; let current = ""; let inQuotes = false; for (let index = 0; index < line.length; index += 1) { const char = line[index]; if (char === '"') { if (inQuotes && line[index + 1] === '"') { current += '"'; index += 1; continue; } inQuotes = !inQuotes; continue; } if (char === "," && !inQuotes) { values.push(current.trim()); current = ""; continue; } current += char; } values.push(current.trim()); return values; }; const lines = body .split("\n") .map((line) => line.trim()) .filter(Boolean); for (const line of lines) { const values = parseCsvLine(line); if (values.length === 0) { continue; } const row = {}; for (let index = 0; index < columns.length; index += 1) { const key = columns[index] ?? `column_${index + 1}`; const raw = values[index] ?? ""; const parsed = parseFiniteNumber(raw); row[key] = parsed ?? raw; } if (values[0]) row.Period = values[0]; if (values[1]) row.Registrator = values[1]; if (values[2]) row.AccountDt = values[2]; if (values[3]) row.AccountKt = values[3]; if (values[4]) row.Amount = parseFiniteNumber(values[4]) ?? values[4]; rows.push(row); } return rows; } function parseExecutePayload(payload) { if (!payload || typeof payload !== "object") { return { ok: false, rows: [], error: "MCP payload is empty or malformed" }; } const source = payload; if (source.success !== true) { return { ok: false, rows: [], error: toStringValue(source.error).trim() || "MCP execute_query returned success=false" }; } if (Array.isArray(source.data)) { const rows = source.data .map((item) => (item && typeof item === "object" ? item : null)) .filter((item) => item !== null); return { ok: true, rows, error: null }; } if (typeof source.data === "string") { return { ok: true, rows: parseRowsFromTextTable(source.data), error: null }; } if (source.data && typeof source.data === "object" && Array.isArray(source.data.rows)) { const rows = (source.data.rows ?? []) .map((item) => (item && typeof item === "object" ? item : null)) .filter((item) => item !== null); return { ok: true, rows, error: null }; } return { ok: true, rows: [], error: null }; } function buildMcpUrl(endpoint) { const normalizedEndpoint = endpoint.startsWith("/") ? endpoint : `/${endpoint}`; const separator = normalizedEndpoint.includes("?") ? "&" : "?"; return `${config_1.ASSISTANT_MCP_PROXY_URL}${normalizedEndpoint}${separator}channel=${encodeURIComponent(config_1.ASSISTANT_MCP_CHANNEL)}`; } function escapeRegExp(value) { return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } function filterRowsByAccountScope(rows, accountScope) { if (accountScope.length === 0) { return rows; } const matchers = accountScope.map((account) => new RegExp(`\\b${escapeRegExp(account)}(?:\\.\\d{1,2})?\\b`, "i")); return rows.filter((row) => { const searchable = Object.values(row) .map((item) => String(item ?? "")) .join(" "); return matchers.some((matcher) => matcher.test(searchable)); }); } async function executeAddressMcpQuery(input) { const endpoint = buildMcpUrl("/api/execute_query"); const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), Math.max(300, config_1.ASSISTANT_MCP_TIMEOUT_MS)); try { const response = await fetch(endpoint, { method: "POST", headers: { "content-type": "application/json; charset=utf-8" }, body: JSON.stringify({ query: input.query, limit: input.limit }), signal: controller.signal }); const responseText = await response.text(); if (!response.ok) { return { fetched_rows: 0, matched_rows: 0, raw_rows: [], rows: [], error: `MCP HTTP ${response.status}: ${responseText.slice(0, 240)}` }; } const payload = responseText.trim() ? JSON.parse(responseText) : {}; const parsed = parseExecutePayload(payload); if (!parsed.ok) { return { fetched_rows: 0, matched_rows: 0, raw_rows: [], rows: [], error: parsed.error }; } const filtered = filterRowsByAccountScope(parsed.rows, Array.isArray(input.account_scope) ? input.account_scope : []); return { fetched_rows: parsed.rows.length, matched_rows: filtered.length, raw_rows: parsed.rows, rows: filtered, error: null }; } catch (error) { const message = error instanceof Error ? error.message : String(error); return { fetched_rows: 0, matched_rows: 0, raw_rows: [], rows: [], error: `MCP fetch failed: ${message}` }; } finally { clearTimeout(timeout); } }