"use strict"; // @ts-nocheck Object.defineProperty(exports, "__esModule", { value: true }); exports.buildInventoryHistoryCapabilityFollowupReply = buildInventoryHistoryCapabilityFollowupReply; exports.buildAddressMemoryRecapReply = buildAddressMemoryRecapReply; exports.buildSelectedObjectAnswerInspectionReply = buildSelectedObjectAnswerInspectionReply; exports.resolveAssistantLivingChatMemoryContext = resolveAssistantLivingChatMemoryContext; exports.createAssistantMemoryRecapPolicy = createAssistantMemoryRecapPolicy; const assistantContinuityPolicy_1 = require("./assistantContinuityPolicy"); function toNonEmptyString(value) { if (value === null || value === undefined) { return null; } const text = String(value).trim(); return text.length > 0 ? text : null; } function collectMessageSamples(input) { const values = [ input.rawUserMessage, input.repairedRawUserMessage, input.effectiveAddressUserMessage, input.repairedEffectiveAddressUserMessage ]; return Array.from(new Set(values .map((item) => String(item ?? "").trim()) .filter((item) => item.length > 0))); } function hasSignalAcrossSamples(samples, detector) { return samples.some((sample) => detector(sample)); } function hasExplicitRecapPromptSignal(samples) { return samples.some((sample) => /(?:что\s+мы\s+.*(?:обсуждали|выяснили)|что\s+уже\s+выяснили|что\s+уже\s+поняли|напомни\s+что\s+мы)/iu.test(sample)); } function buildInventoryHistoryCapabilityFollowupReply(input) { const contextFacts = (0, assistantContinuityPolicy_1.resolveAddressDebugContextFacts)(input.addressDebug, input.toNonEmptyString); const organization = input.organization ?? contextFacts.organization; const lastAsOfDate = contextFacts.scopedDate; const organizationPart = organization ? ` по компании «${organization}»` : ""; const referenceLine = lastAsOfDate ? `Да, могу. Сейчас мы уже смотрели складской срез${organizationPart} на ${lastAsOfDate}.` : `Да, могу показать исторические данные${organizationPart} в этом же складском контуре.`; return [ referenceLine, `Могу показать исторические остатки${organizationPart} за нужный месяц, дату или год.`, "Например:", "- `на март 2020`", "- `на июнь 2016`", "- `за 2017 год`", "- `сравни июнь 2016 с текущим срезом`", "Если хочешь, сразу покажу нужный исторический период." ].join("\n"); } function normalizeRecapIdentity(value) { return String(value ?? "") .trim() .toLowerCase() .replace(/[«»"'`]/g, "") .replace(/\s+/g, " "); } function buildRecapFactLine(input) { const detectedIntent = String(input.debug?.detected_intent ?? ""); const scopedDate = (0, assistantContinuityPolicy_1.resolveAddressDebugContextFacts)(input.debug).scopedDate; const itemPart = input.item ? `по позиции «${input.item}»` : null; const organizationPart = input.organization ? `по компании «${input.organization}»` : null; const datePart = scopedDate ? ` на ${scopedDate}` : ""; if (detectedIntent === "inventory_on_hand_as_of_date") { return `смотрели остатки${organizationPart ? ` ${organizationPart}` : ""}${datePart}`.trim(); } if (detectedIntent === "inventory_purchase_provenance_for_item" && itemPart) { return `разобрали, кто поставлял ${itemPart}${datePart}`.trim(); } if (detectedIntent === "inventory_purchase_documents_for_item" && itemPart) { return `подняли документы закупки ${itemPart}${datePart}`.trim(); } if (detectedIntent === "inventory_sale_trace_for_item" && itemPart) { return `разобрали, кому продавали ${itemPart}${datePart}`.trim(); } if (detectedIntent === "inventory_purchase_to_sale_chain" && itemPart) { return `проследили цепочку от закупки до продажи ${itemPart}${datePart}`.trim(); } if (detectedIntent === "inventory_profitability_for_item" && itemPart) { return `смотрели рентабельность ${itemPart}${datePart}`.trim(); } if (detectedIntent === "inventory_aging_by_purchase_date" && itemPart) { return `смотрели возраст остатков ${itemPart}${datePart}`.trim(); } if (detectedIntent === "counterparty_activity_lifecycle" && organizationPart) { return `смотрели активность в базе 1С ${organizationPart}`.trim(); } if (detectedIntent === "list_documents_by_counterparty" && organizationPart) { return `поднимали документы ${organizationPart}${datePart}`.trim(); } return null; } function collectRecentRecapFacts(input) { const sessionItems = Array.isArray(input.sessionItems) ? input.sessionItems : []; if (sessionItems.length === 0) { return []; } const currentItemKey = normalizeRecapIdentity(input.item); const currentOrganizationKey = normalizeRecapIdentity(input.organization); const facts = []; const seen = new Set(); for (let index = sessionItems.length - 1; index >= 0; index -= 1) { const item = sessionItems[index]; if (!item || item.role !== "assistant" || !item.debug || typeof item.debug !== "object") { continue; } if (!(0, assistantContinuityPolicy_1.isGroundedAddressDebug)(item.debug, input.toNonEmptyString)) { continue; } const debugContext = (0, assistantContinuityPolicy_1.resolveAddressDebugContextFacts)(item.debug, input.toNonEmptyString); const debugItem = debugContext.item; const debugOrganization = debugContext.organization; const itemMatches = currentItemKey ? normalizeRecapIdentity(debugItem) === currentItemKey : false; const organizationMatches = currentOrganizationKey ? normalizeRecapIdentity(debugOrganization) === currentOrganizationKey : false; if (currentItemKey && !itemMatches) { continue; } if (!currentItemKey && currentOrganizationKey && !organizationMatches) { continue; } const fact = buildRecapFactLine({ debug: item.debug, item: debugItem, organization: debugOrganization }); if (!fact || seen.has(fact)) { continue; } seen.add(fact); facts.push(fact); if (facts.length >= 3) { break; } } return facts.reverse(); } function buildAddressMemoryRecapReply(input) { const contextFacts = (0, assistantContinuityPolicy_1.resolveAddressDebugContextFacts)(input.addressDebug, input.toNonEmptyString); const item = contextFacts.item; const organization = input.organization ?? contextFacts.organization; const scopedDate = contextFacts.scopedDate; const recapFacts = collectRecentRecapFacts({ sessionItems: input.sessionItems, item, organization, toNonEmptyString: input.toNonEmptyString }); if (item) { if (recapFacts.length > 0) { const datePart = scopedDate ? ` в срезе на ${scopedDate}` : ""; const organizationPart = organization ? ` по компании «${organization}»` : ""; return [ `Да, помню. По позиции «${item}»${organizationPart}${datePart} мы уже выяснили:`, ...recapFacts.map((fact) => `- ${fact}.`), "Могу сразу продолжить по ней: поставщик, закупка, документы или продажа." ].join("\n"); } const datePart = scopedDate ? ` в срезе на ${scopedDate}` : ""; const organizationPart = organization ? ` по компании «${organization}»` : ""; return [ `Да, помню. Мы обсуждали позицию «${item}»${organizationPart}${datePart}.`, "Могу продолжить по ней без переписывания сущности: кто поставил, когда купили, по каким документам или кому продали." ].join(" "); } if (organization || scopedDate) { const organizationPart = organization ? ` по компании «${organization}»` : ""; const datePart = scopedDate ? ` на ${scopedDate}` : ""; return [ `Да, помню. Мы уже смотрели адресный контур${organizationPart}${datePart}.`, "Могу кратко напомнить контекст или сразу продолжить следующий шаг по этому же сценарию." ].join(" "); } return "Да, помню предыдущий адресный контур. Могу кратко напомнить, что мы уже подтвердили, или сразу продолжить следующий шаг."; } function buildSelectedObjectAnswerInspectionReply(input) { const contextFacts = (0, assistantContinuityPolicy_1.resolveAddressDebugContextFacts)(input.addressDebug, input.toNonEmptyString); const itemLabel = contextFacts.item ?? "эта позиция"; const detectedIntent = String(input.addressDebug?.detected_intent ?? ""); if (detectedIntent === "inventory_sale_trace_for_item") { return [ `Да, если так прозвучало, это ошибка чтения ответа. «${itemLabel}» здесь не контрагент, а сама позиция, по которой мы смотрели продажу.`, "В предыдущем ответе я показывал документы выбытия по этой позиции. Покупатель в доступных данных отдельно не выделен, поэтому назвать контрагента-покупателя я там не мог.", "Если хочешь, следующим шагом могу отдельно проверить, можно ли вытащить покупателя по связанным документам реализации." ].join(" "); } if (detectedIntent === "inventory_purchase_provenance_for_item" || detectedIntent === "inventory_purchase_documents_for_item") { return [ `Да, если так прозвучало, это ошибка чтения ответа. «${itemLabel}» здесь не контрагент, а сама позиция или номенклатура.`, "В предыдущем ответе речь шла о закупке этой позиции: я перечислял поставщиков или закупочные документы по ней, а не называл саму позицию контрагентом." ].join(" "); } return [ `Да, если так прозвучало, это ошибка чтения ответа. «${itemLabel}» здесь не контрагент, а выбранный объект разбора.`, "Я сейчас уточняю именно смысл предыдущего grounded-ответа по этой позиции, а не запускаю новый адресный поиск." ].join(" "); } function resolveAssistantLivingChatMemoryContext(input) { const contextualInventoryHistoryCapabilityFollowup = String(input.modeDecisionReason ?? "") === "inventory_history_capability_followup_detected"; const contextualMemoryRecapFollowup = String(input.modeDecisionReason ?? "") === "memory_recap_followup_detected"; const contextualAnswerInspectionFollowup = String(input.modeDecisionReason ?? "") === "answer_inspection_followup_detected"; const continuity = (0, assistantContinuityPolicy_1.resolveAssistantContinuitySnapshot)({ sessionItems: input.sessionItems, toNonEmptyString }); return { contextualInventoryHistoryCapabilityFollowup, contextualMemoryRecapFollowup, contextualAnswerInspectionFollowup, lastGroundedInventoryAddressDebug: contextualInventoryHistoryCapabilityFollowup ? continuity.lastGroundedInventoryAddressDebug : null, lastMemoryAddressDebug: contextualMemoryRecapFollowup ? continuity.lastGroundedItemAddressDebug ?? continuity.lastGroundedAddressDebug : null, lastAnswerInspectionAddressDebug: contextualAnswerInspectionFollowup ? continuity.lastGroundedItemAddressDebug ?? continuity.lastGroundedAddressDebug : null }; } function createAssistantMemoryRecapPolicy(deps) { function resolveRouteMemorySignals(input) { const samples = collectMessageSamples(input); const continuity = (0, assistantContinuityPolicy_1.resolveAssistantContinuitySnapshot)({ sessionItems: input.sessionItems, toNonEmptyString }); const groundedInventoryContext = continuity.lastGroundedInventoryAddressDebug ?? input.lastGroundedAddressDebug; const historicalCapabilitySignal = hasSignalAcrossSamples(samples, deps.hasHistoricalCapabilityFollowupSignal); const memoryRecapSignal = hasSignalAcrossSamples(samples, deps.hasConversationMemoryRecallFollowupSignal); const explicitRecapPromptSignal = hasExplicitRecapPromptSignal(samples); return { contextualHistoricalCapabilityFollowupDetected: Boolean(input.capabilityMetaQuery && !input.dataScopeMetaQuery && !input.dataRetrievalSignal && historicalCapabilitySignal && deps.isGroundedInventoryContextDebug(groundedInventoryContext)), contextualMemoryRecapFollowupDetected: Boolean(!input.dataScopeMetaQuery && !input.capabilityMetaQuery && !input.aggregateBusinessAnalyticsSignal && memoryRecapSignal && (explicitRecapPromptSignal || (!input.dataRetrievalSignal && !input.strongDataSignal)) && continuity.hasGroundedAddressContext) }; } return { resolveRouteMemorySignals }; }