import { describe, expect, it } from "vitest"; import { buildAddressMemoryRecapReply, buildBroadBusinessEvaluationReply, buildSelectedObjectAnswerInspectionReply, createAssistantMemoryRecapPolicy, resolveAssistantLivingChatMemoryContext } from "../src/services/assistantMemoryRecapPolicy"; const policy = createAssistantMemoryRecapPolicy({ hasHistoricalCapabilityFollowupSignal: (text: unknown) => /историческ|архив|раньше/i.test(String(text ?? "")), hasConversationMemoryRecallFollowupSignal: (text: unknown) => /помнишь|remember/i.test(String(text ?? "")), isGroundedInventoryContextDebug: (debug: unknown) => String((debug as Record | null)?.detected_intent ?? "") === "inventory_on_hand_as_of_date" }); describe("assistantMemoryRecapPolicy", () => { it("detects contextual historical capability follow-up", () => { const signals = policy.resolveRouteMemorySignals({ rawUserMessage: "а исторические остатки тоже можешь?", repairedRawUserMessage: "", effectiveAddressUserMessage: "", repairedEffectiveAddressUserMessage: "", dataScopeMetaQuery: false, capabilityMetaQuery: true, dataRetrievalSignal: false, strongDataSignal: false, aggregateBusinessAnalyticsSignal: false, lastGroundedAddressDebug: { detected_intent: "inventory_on_hand_as_of_date" }, hasPriorAddressDebug: true }); expect(signals.contextualHistoricalCapabilityFollowupDetected).toBe(true); expect(signals.contextualMemoryRecapFollowupDetected).toBe(false); }); it("detects contextual memory recap over prior address debug", () => { const signals = policy.resolveRouteMemorySignals({ rawUserMessage: "а ты помнишь что мы обсуждали?", repairedRawUserMessage: "", effectiveAddressUserMessage: "", repairedEffectiveAddressUserMessage: "", dataScopeMetaQuery: false, capabilityMetaQuery: false, dataRetrievalSignal: false, strongDataSignal: false, aggregateBusinessAnalyticsSignal: false, lastGroundedAddressDebug: null, hasPriorAddressDebug: true, sessionItems: [ { role: "assistant", debug: { execution_lane: "address_query", answer_grounding_check: { status: "grounded" }, detected_intent: "list_documents_by_counterparty" } } ] }); expect(signals.contextualHistoricalCapabilityFollowupDetected).toBe(false); expect(signals.contextualMemoryRecapFollowupDetected).toBe(true); }); it("treats explicit recap wording over selected-object phrasing as memory follow-up even when data cues are present", () => { const signals = policy.resolveRouteMemorySignals({ rawUserMessage: "а ты помнишь, что мы по этой позиции уже выяснили?", repairedRawUserMessage: "", effectiveAddressUserMessage: "", repairedEffectiveAddressUserMessage: "", dataScopeMetaQuery: false, capabilityMetaQuery: false, dataRetrievalSignal: true, strongDataSignal: true, aggregateBusinessAnalyticsSignal: false, lastGroundedAddressDebug: null, hasPriorAddressDebug: true, sessionItems: [ { role: "assistant", debug: { execution_lane: "address_query", answer_grounding_check: { status: "grounded" }, detected_intent: "inventory_purchase_provenance_for_item", extracted_filters: { item: "Рабочая станция", as_of_date: "2022-02-28" } } } ] }); expect(signals.contextualHistoricalCapabilityFollowupDetected).toBe(false); expect(signals.contextualMemoryRecapFollowupDetected).toBe(true); }); it("does not trigger recap from ungrounded address history", () => { const signals = policy.resolveRouteMemorySignals({ rawUserMessage: "а ты помнишь что мы обсуждали?", repairedRawUserMessage: "", effectiveAddressUserMessage: "", repairedEffectiveAddressUserMessage: "", dataScopeMetaQuery: false, capabilityMetaQuery: false, dataRetrievalSignal: false, strongDataSignal: false, aggregateBusinessAnalyticsSignal: false, lastGroundedAddressDebug: null, hasPriorAddressDebug: true, sessionItems: [ { role: "assistant", debug: { execution_lane: "address_query", detected_intent: "inventory_purchase_documents_for_item", extracted_filters: { item: "Рабочая станция" } } } ] }); expect(signals.contextualMemoryRecapFollowupDetected).toBe(false); }); it("detects contextual memory recap over prior grounded MCP discovery answer", () => { const signals = policy.resolveRouteMemorySignals({ rawUserMessage: "а ты помнишь, что мы уже выяснили по свк?", repairedRawUserMessage: "", effectiveAddressUserMessage: "", repairedEffectiveAddressUserMessage: "", dataScopeMetaQuery: false, capabilityMetaQuery: false, dataRetrievalSignal: false, strongDataSignal: false, aggregateBusinessAnalyticsSignal: false, lastGroundedAddressDebug: null, hasPriorAddressDebug: true, sessionItems: [ { role: "assistant", debug: { execution_lane: "living_chat", mcp_discovery_response_applied: true, assistant_mcp_discovery_entry_point_v1: { schema_version: "assistant_mcp_discovery_runtime_entry_point_v1", entry_status: "bridge_executed", turn_input: { turn_meaning_ref: { explicit_entity_candidates: ["Группа СВК"], explicit_date_scope: "2020" } }, bridge: { bridge_status: "answer_draft_ready", business_fact_answer_allowed: true, answer_draft: { answer_mode: "confirmed_with_bounded_inference" } } } } } ] }); expect(signals.contextualMemoryRecapFollowupDetected).toBe(true); }); it("builds deterministic recap summary from recent selected-object facts", () => { const context = resolveAssistantLivingChatMemoryContext({ modeDecisionReason: "memory_recap_followup_detected", sessionItems: [ { role: "assistant", debug: { execution_lane: "address_query", answer_grounding_check: { status: "grounded" }, anchor_type: "item", anchor_value_resolved: "Рабочая станция", extracted_filters: { item: "Рабочая станция", as_of_date: "2022-02-28" } } }, { role: "assistant", debug: { execution_lane: "address_query", answer_grounding_check: { status: "grounded" }, detected_intent: "inventory_purchase_provenance_for_item", extracted_filters: { item: "Рабочая станция", as_of_date: "2022-02-28" } } }, { role: "assistant", debug: { execution_lane: "address_query", answer_grounding_check: { status: "grounded" }, detected_intent: "inventory_purchase_documents_for_item", extracted_filters: { item: "Рабочая станция", as_of_date: "2022-02-28" } } } ] }); const reply = buildAddressMemoryRecapReply({ organization: null, addressDebug: context.lastMemoryAddressDebug, sessionItems: [ { role: "assistant", debug: { execution_lane: "address_query", answer_grounding_check: { status: "grounded" }, detected_intent: "inventory_on_hand_as_of_date", extracted_filters: { organization: "ООО Альтернатива Плюс", as_of_date: "2022-02-28" } } }, { role: "assistant", debug: { execution_lane: "address_query", answer_grounding_check: { status: "grounded" }, detected_intent: "inventory_purchase_provenance_for_item", extracted_filters: { item: "Рабочая станция", as_of_date: "2022-02-28" } } }, { role: "assistant", debug: { execution_lane: "address_query", answer_grounding_check: { status: "grounded" }, detected_intent: "inventory_purchase_documents_for_item", extracted_filters: { item: "Рабочая станция", as_of_date: "2022-02-28" } } } ], toNonEmptyString: (value: unknown) => { const text = String(value ?? "").trim(); return text.length > 0 ? text : null; } }); expect(context.contextualMemoryRecapFollowup).toBe(true); expect(reply).toContain("Рабочая станция"); expect(reply).toContain("мы уже выяснили"); expect(reply).toContain("разобрали, кто поставлял"); expect(reply).toContain("подняли документы закупки"); }); it("resolves grounded answer inspection from shared memory context", () => { const context = resolveAssistantLivingChatMemoryContext({ modeDecisionReason: "answer_inspection_followup_detected", sessionItems: [ { role: "assistant", debug: { execution_lane: "address_query", answer_grounding_check: { status: "grounded" }, detected_intent: "inventory_sale_trace_for_item", extracted_filters: { item: "Рабочая станция", organization: "ООО Альтернатива Плюс", as_of_date: "2016-03-31" } } } ] }); const reply = buildSelectedObjectAnswerInspectionReply({ addressDebug: context.lastAnswerInspectionAddressDebug, toNonEmptyString: (value: unknown) => { const text = String(value ?? "").trim(); return text.length > 0 ? text : null; } }); expect(context.contextualAnswerInspectionFollowup).toBe(true); expect(reply).toContain("не контрагент"); expect(reply).toContain("Рабочая станция"); expect(reply).toContain("Покупатель"); }); it("builds deterministic recap summary from grounded MCP discovery counterparty context", () => { const sessionItems = [ { role: "assistant", debug: { execution_lane: "living_chat", mcp_discovery_response_applied: true, assistant_mcp_discovery_entry_point_v1: { schema_version: "assistant_mcp_discovery_runtime_entry_point_v1", entry_status: "bridge_executed", turn_input: { turn_meaning_ref: { explicit_entity_candidates: ["Группа СВК"], explicit_organization_scope: "ООО Альтернатива Плюс", explicit_date_scope: "2020" } }, bridge: { bridge_status: "answer_draft_ready", business_fact_answer_allowed: true, answer_draft: { answer_mode: "confirmed_with_bounded_inference" }, pilot: { pilot_scope: "counterparty_bidirectional_value_flow_query_movements_v1", derived_bidirectional_value_flow: { net_amount_human_ru: "3 865 501,50 руб.", incoming_customer_revenue: { total_amount_human_ru: "47 628 853,03 руб." }, outgoing_supplier_payout: { total_amount_human_ru: "43 763 351,53 руб." } } } } } } } ]; const context = resolveAssistantLivingChatMemoryContext({ modeDecisionReason: "memory_recap_followup_detected", sessionItems }); const reply = buildAddressMemoryRecapReply({ organization: null, addressDebug: context.lastMemoryAddressDebug, sessionItems, toNonEmptyString: (value: unknown) => { const text = String(value ?? "").trim(); return text.length > 0 ? text : null; } }); expect(context.contextualMemoryRecapFollowup).toBe(true); expect(reply).toContain("Группа СВК"); expect(reply).toContain("нетто"); expect(reply).toContain("47 628 853,03 руб."); expect(reply).toContain("43 763 351,53 руб."); }); it("builds deterministic recap summary from grounded MCP metadata discovery context", () => { const sessionItems = [ { role: "assistant", debug: { execution_lane: "living_chat", mcp_discovery_response_applied: true, assistant_mcp_discovery_entry_point_v1: { schema_version: "assistant_mcp_discovery_runtime_entry_point_v1", entry_status: "bridge_executed", turn_input: { turn_meaning_ref: { explicit_entity_candidates: ["НДС"] } }, bridge: { bridge_status: "answer_draft_ready", business_fact_answer_allowed: true, answer_draft: { answer_mode: "confirmed_with_bounded_inference" }, pilot: { pilot_scope: "metadata_inspection_v1", derived_metadata_surface: { metadata_scope: "НДС", matched_rows: 7, matched_objects: ["РегистрНакопления.НДСПокупок"], available_entity_sets: ["accumulation_register", "document"], available_fields: ["amount", "vat_rate", "organization"] } } } } } } ]; const context = resolveAssistantLivingChatMemoryContext({ modeDecisionReason: "memory_recap_followup_detected", sessionItems }); const reply = buildAddressMemoryRecapReply({ organization: null, addressDebug: context.lastMemoryAddressDebug, sessionItems, toNonEmptyString: (value: unknown) => { const text = String(value ?? "").trim(); return text.length > 0 ? text : null; } }); expect(context.contextualMemoryRecapFollowup).toBe(true); expect(reply).toContain("НДС"); expect(reply).toContain("схему 1С"); expect(reply).toContain("amount"); expect(reply).toContain("accumulation_register"); }); it("builds deterministic broad business evaluation summary from recent grounded organization facts", () => { const sessionItems = [ { role: "assistant", debug: { execution_lane: "address_query", answer_grounding_check: { status: "grounded" }, detected_intent: "counterparty_activity_lifecycle", extracted_filters: { organization: "ООО Альтернатива Плюс" } } }, { role: "assistant", debug: { execution_lane: "living_chat", mcp_discovery_response_applied: true, assistant_mcp_discovery_entry_point_v1: { schema_version: "assistant_mcp_discovery_runtime_entry_point_v1", entry_status: "bridge_executed", turn_input: { turn_meaning_ref: { explicit_entity_candidates: ["Группа СВК"], explicit_organization_scope: "ООО Альтернатива Плюс", explicit_date_scope: "2020" } }, bridge: { bridge_status: "answer_draft_ready", business_fact_answer_allowed: true, answer_draft: { answer_mode: "confirmed_with_bounded_inference" }, pilot: { pilot_scope: "counterparty_bidirectional_value_flow_query_movements_v1", derived_bidirectional_value_flow: { net_amount_human_ru: "3 865 501,50 руб.", incoming_customer_revenue: { total_amount_human_ru: "47 628 853,03 руб." }, outgoing_supplier_payout: { total_amount_human_ru: "43 763 351,53 руб." } } } } } } } ]; const reply = buildBroadBusinessEvaluationReply({ organization: "ООО Альтернатива Плюс", addressDebug: sessionItems[1].debug as any, sessionItems, toNonEmptyString: (value: unknown) => { const text = String(value ?? "").trim(); return text.length > 0 ? text : null; } }); expect(reply.toLowerCase()).toContain("оценка бизнеса"); expect(reply).toContain("ООО Альтернатива Плюс"); expect(reply).toContain("47 628 853,03"); }); it("builds grounded answer inspection reply for MCP discovery net answer", () => { const context = resolveAssistantLivingChatMemoryContext({ modeDecisionReason: "answer_inspection_followup_detected", sessionItems: [ { role: "assistant", debug: { execution_lane: "living_chat", mcp_discovery_response_applied: true, assistant_mcp_discovery_entry_point_v1: { schema_version: "assistant_mcp_discovery_runtime_entry_point_v1", entry_status: "bridge_executed", turn_input: { turn_meaning_ref: { explicit_entity_candidates: ["Группа СВК"], explicit_date_scope: "2020" } }, bridge: { bridge_status: "answer_draft_ready", business_fact_answer_allowed: true, answer_draft: { answer_mode: "confirmed_with_bounded_inference" }, pilot: { pilot_scope: "counterparty_bidirectional_value_flow_query_movements_v1" } } } } } ] }); const reply = buildSelectedObjectAnswerInspectionReply({ addressDebug: context.lastAnswerInspectionAddressDebug, toNonEmptyString: (value: unknown) => { const text = String(value ?? "").trim(); return text.length > 0 ? text : null; } }); expect(context.contextualAnswerInspectionFollowup).toBe(true); expect(reply).toContain("Группа СВК"); expect(reply).toContain("Нетто"); expect(reply).toContain("проверенному периоду"); }); });