NODEDC_1C/llm_normalizer/backend/tests/addressNavigationState.test.ts

329 lines
14 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { describe, expect, it } from "vitest";
import {
createEmptyAddressNavigationState,
evolveAddressNavigationStateWithAssistantItem,
normalizeAddressNavigationState
} from "../src/services/addressNavigationState";
describe("address navigation state", () => {
it("creates default empty state", () => {
const state = createEmptyAddressNavigationState("asst-1", "2026-04-12T10:00:00.000Z");
expect(state.schema_version).toBe("address_navigation_state_v1");
expect(state.session_id).toBe("asst-1");
expect(state.result_sets).toEqual([]);
expect(state.navigation_history).toEqual([]);
expect(state.session_context.active_result_set_id).toBeNull();
});
it("captures result_set and focus from address assistant turn", () => {
const base = createEmptyAddressNavigationState("asst-2", "2026-04-12T10:00:00.000Z");
const assistantItem = {
message_id: "msg-a1",
session_id: "asst-2",
role: "assistant",
text: [
"Топ-6 заказчиков по сумме поступлений:",
"1. Группа | сумма: 12093465 | операций: 13",
"4. Гамма-мебель, ООО | сумма: 471000 | операций: 2"
].join("\n"),
reply_type: "factual",
created_at: "2026-04-12T10:00:10.000Z",
trace_id: "address-123",
debug: {
detected_mode: "address_query",
detected_intent: "customer_revenue_and_payments",
selected_recipe: "address_customer_revenue_and_payments_v1",
extracted_filters: {
period_from: "2020-01-01",
period_to: "2020-12-31"
},
anchor_type: "counterparty",
anchor_value_resolved: "Гамма-мебель, ООО",
dialog_continuation_contract_v2: {
decision: "new_topic"
}
}
} as any;
const evolved = evolveAddressNavigationStateWithAssistantItem(base, assistantItem, 2);
expect(evolved.result_sets.length).toBe(1);
expect(evolved.result_sets[0]?.result_set_id).toBe("rs-msg-a1");
expect(evolved.result_sets[0]?.intent).toBe("customer_revenue_and_payments");
expect(evolved.result_sets[0]?.entity_refs.length).toBeGreaterThan(0);
expect(evolved.session_context.active_result_set_id).toBe("rs-msg-a1");
expect(evolved.session_context.active_focus_object?.label).toBe("Гамма-мебель, ООО");
expect(evolved.navigation_history[0]?.action).toBe("open");
});
it("tracks drilldown event for follow-up continuation turn", () => {
const initial = normalizeAddressNavigationState(
{
schema_version: "address_navigation_state_v1",
session_id: "asst-3",
updated_at: "2026-04-12T10:00:00.000Z",
session_context: {
active_result_set_id: "rs-prev",
active_focus_object: null,
last_confirmed_route: "address_customer_revenue_and_payments_v1",
date_scope: {
as_of_date: null,
period_from: "2020-01-01",
period_to: "2020-12-31"
},
organization_scope: null
},
result_sets: [],
navigation_history: []
} as any,
"asst-3"
);
const assistantItem = {
message_id: "msg-a2",
session_id: "asst-3",
role: "assistant",
text: "Собран список договоров по контрагенту Гамма-мебель, ООО.",
reply_type: "factual",
created_at: "2026-04-12T10:02:00.000Z",
trace_id: "address-456",
debug: {
detected_mode: "address_query",
detected_intent: "list_contracts_by_counterparty",
selected_recipe: "address_contracts_by_counterparty_v1",
extracted_filters: {
period_from: "2020-01-01",
period_to: "2020-12-31",
counterparty: "Гамма-мебель, ООО"
},
anchor_type: "counterparty",
anchor_value_resolved: "Гамма-мебель, ООО",
dialog_continuation_contract_v2: {
decision: "continue_previous"
}
}
} as any;
const evolved = evolveAddressNavigationStateWithAssistantItem(initial, assistantItem, 4);
expect(evolved.navigation_history.length).toBe(1);
expect(evolved.navigation_history[0]?.action).toBe("drilldown");
expect(evolved.navigation_history[0]?.source_result_set_id).toBe("rs-prev");
expect(evolved.session_context.active_result_set_id).toBe("rs-msg-a2");
expect(evolved.session_context.active_focus_object?.object_type).toBe("counterparty");
expect(evolved.session_context.date_scope.period_from).toBe("2020-01-01");
expect(evolved.session_context.date_scope.period_to).toBe("2020-12-31");
});
it("prefers grounded discovery counterparty over stale referential anchor when updating focus", () => {
const initial = normalizeAddressNavigationState(
{
schema_version: "address_navigation_state_v1",
session_id: "asst-3b",
updated_at: "2026-04-12T10:00:00.000Z",
session_context: {
active_result_set_id: "rs-prev",
active_focus_object: {
object_type: "counterparty",
object_id: "counterparty:нортон",
label: "НОРТОН",
provenance_result_set_id: "rs-prev",
selected_at: "2026-04-12T09:59:00.000Z"
},
last_confirmed_route: "address_customer_revenue_and_payments_v1",
date_scope: {
as_of_date: null,
period_from: "2020-01-01",
period_to: "2020-12-31"
},
organization_scope: "ООО Альтернатива Плюс"
},
result_sets: [],
navigation_history: []
} as any,
"asst-3b"
);
const assistantItem = {
message_id: "msg-a2b",
session_id: "asst-3b",
role: "assistant",
text: "По Группа СВК подтверждены исходящие платежи за 2020 год.",
reply_type: "factual",
created_at: "2026-04-12T10:02:30.000Z",
trace_id: "address-456b",
debug: {
detected_mode: "address_query",
detected_intent: "supplier_payouts_profile",
selected_recipe: "address_supplier_payouts_profile_v1",
extracted_filters: {
counterparty: "НОРТОН",
period_from: "2020-01-01",
period_to: "2020-12-31"
},
anchor_type: "counterparty",
anchor_value_raw: "он",
anchor_value_resolved: "он",
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: {
asked_domain_family: "counterparty_value",
asked_action_family: "payout",
explicit_entity_candidates: ["Группа СВК"]
}
},
bridge: {
bridge_status: "answer_draft_ready",
business_fact_answer_allowed: true,
pilot: {
pilot_scope: "counterparty_supplier_payout_query_movements_v1"
},
answer_draft: {
answer_mode: "confirmed_factual"
}
}
},
dialog_continuation_contract_v2: {
decision: "continue_previous"
}
}
} as any;
const evolved = evolveAddressNavigationStateWithAssistantItem(initial, assistantItem, 4);
expect(evolved.session_context.active_focus_object?.object_type).toBe("counterparty");
expect(evolved.session_context.active_focus_object?.label).toBe("Группа СВК");
expect(evolved.session_context.active_focus_object?.object_id).toBe("counterparty:группа свк");
expect(evolved.navigation_history[0]?.target_object_id).toBe("counterparty:группа свк");
});
it("captures item focus from inventory answers when no anchor is materialized", () => {
const base = createEmptyAddressNavigationState("asst-4", "2026-04-12T10:00:00.000Z");
const assistantItem = {
message_id: "msg-a3",
session_id: "asst-4",
role: "assistant",
text: "Собран подтвержденный закупочный след по товару Диван трехместный до 14.04.2026.\n\n1. Авансовый отчет 00000000004 от 24.08.2018 12:00:04 | дата: 24.08.2018 | сумма: 34.490,00 ₽ | склад: Основной склад",
reply_type: "factual",
created_at: "2026-04-12T10:03:00.000Z",
trace_id: "address-789",
debug: {
detected_mode: "address_query",
detected_intent: "inventory_purchase_provenance_for_item",
selected_recipe: "address_inventory_purchase_provenance_for_item_v1",
extracted_filters: {
item: "Диван трехместный",
warehouse: "Основной склад",
as_of_date: "2026-04-14"
},
anchor_type: "unknown",
anchor_value_resolved: null,
anchor_value_raw: null,
dialog_continuation_contract_v2: {
decision: "new_topic"
}
}
} as any;
const evolved = evolveAddressNavigationStateWithAssistantItem(base, assistantItem, 3);
expect(evolved.session_context.active_focus_object?.label).toBe("Диван трехместный");
expect(evolved.session_context.active_focus_object?.provenance_result_set_id).toBe("rs-msg-a3");
});
it("derives single organization scope from inventory answer text when filters omit organization", () => {
const base = createEmptyAddressNavigationState("asst-5", "2026-04-12T10:00:00.000Z");
const assistantItem = {
message_id: "msg-a4",
session_id: "asst-5",
role: "assistant",
text: [
"На 31.05.2020 на складе подтверждено 1 позиция.",
"1. Пуф арий | склад: Основной склад | количество: 1,000 | стоимость: 6.490,00 ₽ | организация: ООО Альтернатива Плюс | дата строки: 2020-05-31T23:59:59Z"
].join("\n"),
reply_type: "factual",
created_at: "2026-04-12T10:04:00.000Z",
trace_id: "address-790",
debug: {
detected_mode: "address_query",
detected_intent: "inventory_on_hand_as_of_date",
selected_recipe: "address_inventory_on_hand_as_of_date_v1",
extracted_filters: {
as_of_date: "2020-05-31"
},
anchor_type: "unknown",
anchor_value_resolved: null,
anchor_value_raw: null,
dialog_continuation_contract_v2: {
decision: "new_topic"
}
}
} as any;
const evolved = evolveAddressNavigationStateWithAssistantItem(base, assistantItem, 4);
expect(evolved.result_sets[0]?.type).toBe("inventory_snapshot");
expect(evolved.result_sets[0]?.filters.organization).toBe("ООО Альтернатива Плюс");
expect(evolved.result_sets[0]?.entity_refs[0]?.entity_type).toBe("item");
expect(evolved.result_sets[0]?.entity_refs[0]?.value).toBe("Пуф арий");
expect(evolved.session_context.organization_scope).toBe("ООО Альтернатива Плюс");
expect(evolved.session_context.active_focus_object).toBeNull();
});
it("resets stale focus and date scope on explicit new topic turn", () => {
const initial = normalizeAddressNavigationState(
{
schema_version: "address_navigation_state_v1",
session_id: "asst-6",
updated_at: "2026-04-12T10:00:00.000Z",
session_context: {
active_result_set_id: "rs-prev",
active_focus_object: {
object_type: "counterparty",
object_id: "counterparty:chapurnov",
label: "Чепурнов",
provenance_result_set_id: "rs-prev",
selected_at: "2026-04-12T09:59:00.000Z"
},
last_confirmed_route: "address_documents_by_counterparty_v1",
date_scope: {
as_of_date: null,
period_from: "2017-01-01",
period_to: "2017-12-31"
},
organization_scope: "ООО Альтернатива Плюс"
},
result_sets: [],
navigation_history: []
} as any,
"asst-6"
);
const assistantItem = {
message_id: "msg-a5",
session_id: "asst-6",
role: "assistant",
text: "На 16.04.2026 на складе подтверждено 11 позиций.",
reply_type: "factual",
created_at: "2026-04-12T10:05:00.000Z",
trace_id: "address-791",
debug: {
detected_mode: "address_query",
detected_intent: "inventory_on_hand_as_of_date",
selected_recipe: "address_inventory_on_hand_as_of_date_v1",
extracted_filters: {
as_of_date: "2026-04-16",
organization: "ООО Альтернатива Плюс"
},
anchor_type: "organization",
anchor_value_resolved: "ООО Альтернатива Плюс",
dialog_continuation_contract_v2: {
decision: "new_topic"
}
}
} as any;
const evolved = evolveAddressNavigationStateWithAssistantItem(initial, assistantItem, 5);
expect(evolved.session_context.active_result_set_id).toBe("rs-msg-a5");
expect(evolved.session_context.active_focus_object?.label).toBe("ООО Альтернатива Плюс");
expect(evolved.session_context.date_scope.as_of_date).toBe("2026-04-16");
expect(evolved.session_context.date_scope.period_from).toBeNull();
expect(evolved.session_context.date_scope.period_to).toBeNull();
expect(evolved.session_context.last_confirmed_route).toBe("address_inventory_on_hand_as_of_date_v1");
expect(evolved.navigation_history[0]?.action).toBe("open");
});
});