"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ASSISTANT_MCP_DISCOVERY_RESPONSE_CANDIDATE_SCHEMA_VERSION = void 0; exports.buildAssistantMcpDiscoveryResponseCandidate = buildAssistantMcpDiscoveryResponseCandidate; exports.ASSISTANT_MCP_DISCOVERY_RESPONSE_CANDIDATE_SCHEMA_VERSION = "assistant_mcp_discovery_response_candidate_v1"; function toRecordObject(value) { if (!value || typeof value !== "object" || Array.isArray(value)) { return null; } return value; } function toNonEmptyString(value) { if (value === null || value === undefined) { return null; } const text = String(value).trim(); return text.length > 0 ? text : null; } function toStringList(value) { if (!Array.isArray(value)) { return []; } return value.map((item) => toNonEmptyString(item)).filter((item) => Boolean(item)); } function normalizeReasonCode(value) { const normalized = value .trim() .replace(/[^\p{L}\p{N}_.:-]+/gu, "_") .replace(/^_+|_+$/g, "") .toLowerCase(); return normalized.length > 0 ? normalized.slice(0, 120) : null; } function pushReason(target, value) { const normalized = normalizeReasonCode(value); if (normalized && !target.includes(normalized)) { target.push(normalized); } } function uniqueStrings(values) { const result = []; for (const value of values) { const text = String(value ?? "").trim(); if (text && !result.includes(text)) { result.push(text); } } return result; } function hasInternalMechanics(value) { const text = value.toLowerCase(); return (text.includes("query_documents") || text.includes("query_movements") || text.includes("primitive") || text.includes("pilot_") || text.includes("runtime_") || text.includes("planner_") || text.includes("catalog_") || text.includes("select ")); } function userFacingLines(values) { return uniqueStrings(values).filter((line) => !hasInternalMechanics(line)); } function localizeLine(value) { const counterpartyMatch = value.match(/^1C activity rows were found for counterparty\s+(.+)$/i); if (counterpartyMatch) { return `В 1С найдены строки активности по контрагенту ${counterpartyMatch[1]}.`; } if (/^1C activity rows were found for the requested counterparty scope$/i.test(value)) { return "В 1С найдены строки активности по запрошенному контрагентскому контуру."; } const valueFlowMatch = value.match(/^1C value-flow rows were found for counterparty\s+(.+)$/i); if (valueFlowMatch) { return `В 1С найдены строки денежных движений по контрагенту ${valueFlowMatch[1]}.`; } if (/^1C value-flow rows were found for the requested counterparty scope$/i.test(value)) { return "В 1С найдены строки денежных движений по запрошенному контрагентскому контуру."; } const supplierPayoutMatch = value.match(/^1C supplier-payout rows were found for counterparty\s+(.+)$/i); if (supplierPayoutMatch) { return `В 1С найдены строки исходящих платежей/списаний по контрагенту ${supplierPayoutMatch[1]}.`; } if (/^1C supplier-payout rows were found for the requested counterparty scope$/i.test(value)) { return "В 1С найдены строки исходящих платежей/списаний по запрошенному контрагентскому контуру."; } const bidirectionalMatch = value.match(/^1C bidirectional value-flow rows were checked for counterparty\s+(.+): incoming=(found|not_found), outgoing=(found|not_found)$/i); if (bidirectionalMatch) { const incoming = bidirectionalMatch[2] === "found" ? "входящие строки найдены" : "входящие строки не найдены"; const outgoing = bidirectionalMatch[3] === "found" ? "исходящие строки найдены" : "исходящие строки не найдены"; return `В 1С проверены входящие и исходящие денежные строки по контрагенту ${bidirectionalMatch[1]}: ${incoming}, ${outgoing}.`; } const bidirectionalScopeMatch = value.match(/^1C bidirectional value-flow rows were checked for the requested counterparty scope: incoming=(found|not_found), outgoing=(found|not_found)$/i); if (bidirectionalScopeMatch) { const incoming = bidirectionalScopeMatch[1] === "found" ? "входящие строки найдены" : "входящие строки не найдены"; const outgoing = bidirectionalScopeMatch[2] === "found" ? "исходящие строки найдены" : "исходящие строки не найдены"; return `В 1С проверены входящие и исходящие денежные строки по запрошенному контрагентскому контуру: ${incoming}, ${outgoing}.`; } if (/^Business activity duration may be inferred from first and latest confirmed 1C activity rows$/i.test(value)) { return "Длительность деловой активности можно оценивать только как вывод по первой и последней подтвержденной строке активности в 1С."; } if (/^Counterparty value-flow total was calculated from confirmed 1C movement rows$/i.test(value)) { return "Сумма рассчитана только по подтвержденным строкам денежных движений в 1С."; } if (/^Counterparty monthly value-flow breakdown was grouped by month over confirmed 1C movement rows$/i.test(value)) { return "Помесячная раскладка денежного потока сгруппирована только по подтвержденным строкам движений 1С."; } if (/^Counterparty supplier-payout total was calculated from confirmed 1C outgoing payment rows$/i.test(value)) { return "Сумма исходящих платежей рассчитана только по подтвержденным строкам списаний в 1С."; } if (/^Counterparty net value-flow was calculated as incoming confirmed 1C rows minus outgoing confirmed 1C rows$/i.test(value)) { return "Нетто денежного потока рассчитано только как входящие подтвержденные строки 1С минус исходящие подтвержденные строки 1С."; } if (/^Counterparty monthly net value-flow breakdown was grouped by month over confirmed incoming and outgoing 1C rows$/i.test(value)) { return "Помесячная нетто-раскладка сгруппирована только по подтвержденным входящим и исходящим строкам 1С."; } if (/^Legal registration date is not proven by this MCP discovery pilot$/i.test(value)) { return "Юридическая дата регистрации этим поиском не подтверждена."; } if (/^Complete requested-period coverage is not proven because the MCP discovery probe row limit was reached$/i.test(value)) { return "Полное покрытие запрошенного периода не подтверждено: проверка достигла лимита найденных строк."; } if (/^Complete requested-period coverage for bidirectional value-flow is not proven because at least one MCP discovery probe row limit was reached$/i.test(value)) { return "Полное покрытие запрошенного периода по двустороннему денежному потоку не подтверждено: хотя бы одна сторона проверки достигла лимита найденных строк."; } if (/^Full turnover outside the checked period is not proven by this MCP discovery pilot$/i.test(value)) { return "Полный оборот вне проверенного периода этим поиском не подтвержден."; } if (/^Full all-time turnover is not proven without an explicit checked period$/i.test(value)) { return "Полный оборот за все время без явно проверенного периода не подтвержден."; } if (/^Full supplier-payout amount outside the checked period is not proven by this MCP discovery pilot$/i.test(value)) { return "Полный объем исходящих платежей вне проверенного периода этим поиском не подтвержден."; } if (/^Full all-time supplier-payout amount is not proven without an explicit checked period$/i.test(value)) { return "Полный объем исходящих платежей за все время без явно проверенного периода не подтвержден."; } if (/^Full bidirectional value-flow outside the checked period is not proven by this MCP discovery pilot$/i.test(value)) { return "Полный двусторонний денежный поток вне проверенного периода этим поиском не подтвержден."; } if (/^Full all-time bidirectional value-flow is not proven without an explicit checked period$/i.test(value)) { return "Полный двусторонний денежный поток за все время без явно проверенного периода не подтвержден."; } if (/^Requested period coverage was recovered through monthly 1C value-flow probes after the broad probe hit the row limit$/i.test(value)) { return "Покрытие запрошенного периода восстановлено помесячными проверками 1С после того, как общая выборка уперлась в лимит строк."; } if (/^Requested period coverage for bidirectional value-flow was recovered through monthly 1C side probes after a broad probe hit the row limit$/i.test(value)) { return "Покрытие запрошенного периода по двустороннему денежному потоку восстановлено помесячными проверками 1С после того, как общая выборка уперлась в лимит строк хотя бы по одной стороне."; } return value; } function section(title, lines) { const clean = userFacingLines(lines.map(localizeLine)); if (clean.length === 0) { return null; } return `${title}\n${clean.map((line) => `- ${line}`).join("\n")}`; } function statusFrom(entryPoint) { if (!entryPoint || entryPoint.entry_status === "skipped_not_applicable") { return "not_applicable"; } if (entryPoint.entry_status === "skipped_needs_more_context") { return "clarification_candidate"; } const bridgeStatus = toNonEmptyString(toRecordObject(entryPoint.bridge)?.bridge_status); if (bridgeStatus === "answer_draft_ready") { return "ready_for_guarded_use"; } if (bridgeStatus === "needs_clarification") { return "clarification_candidate"; } if (bridgeStatus === "checked_sources_only") { return "checked_sources_only_candidate"; } if (bridgeStatus === "blocked") { return "blocked"; } if (bridgeStatus === "unsupported") { return "unsupported"; } return "not_applicable"; } function replyTypeFor(status) { if (status === "clarification_candidate") { return "clarification_required"; } if (status === "blocked" || status === "unsupported" || status === "not_applicable") { return "no_grounded_answer"; } return "partial_coverage"; } function buildReplyText(entryPoint, status) { const bridge = toRecordObject(entryPoint.bridge); const draft = toRecordObject(bridge?.answer_draft); if (!draft) { if (status === "clarification_candidate") { return "Нужно уточнить контекст перед поиском в 1С: контрагента, период или организацию."; } return null; } const blocks = [ toNonEmptyString(draft.headline) ? `Коротко: ${localizeLine(String(draft.headline))}` : null, section("Что подтверждено:", toStringList(draft.confirmed_lines)), section("Что можно сказать только как вывод:", toStringList(draft.inference_lines)), section("Что не подтверждено:", toStringList(draft.unknown_lines)), section("Ограничения проверки:", toStringList(draft.limitation_lines)), toNonEmptyString(draft.next_step_line) ? `Следующий шаг: ${localizeLine(String(draft.next_step_line))}` : null ].filter((item) => Boolean(item)); const reply = blocks.join("\n\n").trim(); return reply.length > 0 && !hasInternalMechanics(reply) ? reply : null; } function buildAssistantMcpDiscoveryResponseCandidate(entryPoint) { const entry = entryPoint ?? null; const status = statusFrom(entry); const reasonCodes = uniqueStrings(entry?.reason_codes ?? []); pushReason(reasonCodes, `mcp_discovery_response_candidate_${status}`); pushReason(reasonCodes, "mcp_discovery_response_candidate_not_hot_wired"); const replyText = entry && (status === "ready_for_guarded_use" || status === "checked_sources_only_candidate" || status === "clarification_candidate") ? buildReplyText(entry, status) : null; return { schema_version: exports.ASSISTANT_MCP_DISCOVERY_RESPONSE_CANDIDATE_SCHEMA_VERSION, policy_owner: "assistantMcpDiscoveryResponseCandidate", candidate_status: replyText ? status : status === "clarification_candidate" ? status : status, hot_runtime_wired: false, reply_type: replyTypeFor(status), reply_text: replyText, eligible_for_future_hot_runtime: Boolean(replyText) && (status === "ready_for_guarded_use" || status === "checked_sources_only_candidate" || status === "clarification_candidate"), must_keep_internal_mechanics_hidden: true, reason_codes: reasonCodes }; }