import { describe, expect, it, vi } from "vitest"; import { runAssistantMcpDiscoveryRuntimeEntryPoint } from "../src/services/assistantMcpDiscoveryRuntimeEntryPoint"; function buildDeps(rows: Array>, error: string | null = null) { return { executeAddressMcpQuery: vi.fn(async () => ({ fetched_rows: rows.length, matched_rows: error ? 0 : rows.length, raw_rows: rows, rows: error ? [] : rows, error })) }; } function buildMetadataDeps(rows: Array>, error: string | null = null) { return { executeAddressMcpMetadata: vi.fn(async () => ({ fetched_rows: error ? 0 : rows.length, raw_rows: error ? [] : rows, rows: error ? [] : rows, error })) }; } describe("assistant MCP discovery runtime entry point", () => { it("runs the bridge for discovery-eligible lifecycle turn context", async () => { const result = await runAssistantMcpDiscoveryRuntimeEntryPoint({ userMessage: "Сколько лет мы работаем с Группа СВК?", predecomposeContract: { entities: { counterparty: "Группа СВК" }, period: {} }, deps: buildDeps([{ Период: "2020-01-15T00:00:00", Регистратор: "CP_CUSTOMER_ACTIVITY_FIRST" }]) }); expect(result.entry_status).toBe("bridge_executed"); expect(result.hot_runtime_wired).toBe(false); expect(result.discovery_attempted).toBe(true); expect(result.turn_input.semantic_data_need).toBe("counterparty lifecycle evidence"); expect(result.bridge?.bridge_status).toBe("answer_draft_ready"); expect(result.bridge?.answer_draft.answer_mode).toBe("confirmed_with_bounded_inference"); expect(result.reason_codes).toContain("runtime_entry_point_bridge_executed"); }); it("skips supported exact turns before any discovery execution", async () => { const deps = buildDeps([]); const result = await runAssistantMcpDiscoveryRuntimeEntryPoint({ assistantTurnMeaning: { asked_domain_family: "counterparty", asked_action_family: "list_documents", explicit_intent_candidate: "list_documents_by_counterparty", explicit_entity_candidates: [{ value: "SVK" }] }, deps }); expect(result.entry_status).toBe("skipped_not_applicable"); expect(result.discovery_attempted).toBe(false); expect(result.bridge).toBeNull(); expect(deps.executeAddressMcpQuery).not.toHaveBeenCalled(); expect(result.reason_codes).toContain("runtime_entry_point_skipped_supported_exact_turn"); }); it("passes unsupported-but-understood value turns into bridge with normalized entity scope", async () => { const result = await runAssistantMcpDiscoveryRuntimeEntryPoint({ assistantTurnMeaning: { asked_domain_family: "counterparty", asked_action_family: "counterparty_value_or_turnover", unsupported_but_understood_family: "counterparty_value_or_turnover", explicit_entity_candidates: [{ value: "SVK" }] }, predecomposeContract: { entities: { counterparty: "Группа СВК" }, period: { period_from: "2020-01-01", period_to: "2020-12-31" } }, deps: buildDeps([ { Period: "2020-01-15T00:00:00", Amount: 1250, Counterparty: "SVK" }, { Period: "2020-02-20T00:00:00", Amount: 2500, Counterparty: "SVK" } ]) }); expect(result.entry_status).toBe("bridge_executed"); expect(result.turn_input.turn_meaning_ref?.explicit_entity_candidates).toEqual(["SVK", "Группа СВК"]); expect(result.bridge?.bridge_status).toBe("answer_draft_ready"); expect(result.bridge?.pilot.pilot_scope).toBe("counterparty_value_flow_query_movements_v1"); expect(result.bridge?.pilot.derived_value_flow?.total_amount).toBe(3750); expect(result.bridge?.hot_runtime_wired).toBe(false); expect(result.reason_codes).toContain("mcp_discovery_unsupported_but_understood_turn"); }); it("runs the bridge for raw metadata wording without an exact route owner", async () => { const result = await runAssistantMcpDiscoveryRuntimeEntryPoint({ userMessage: "какие документы и поля есть в 1С по НДС?", deps: buildMetadataDeps([ { FullName: "Документ.СчетФактураВыданный", MetaType: "Документ", attributes: [{ Name: "Дата" }] } ]) }); expect(result.entry_status).toBe("bridge_executed"); expect(result.discovery_attempted).toBe(true); expect(result.turn_input.semantic_data_need).toBe("1C metadata evidence"); expect(result.turn_input.turn_meaning_ref).toMatchObject({ asked_domain_family: "metadata", asked_action_family: "inspect_fields" }); expect(result.bridge?.pilot.pilot_scope).toBe("metadata_inspection_v1"); expect(result.bridge?.answer_draft.headline).toContain("метаданным 1С"); }); it("runs the bridge for raw entity-resolution wording and executes the full grounding chain", async () => { const result = await runAssistantMcpDiscoveryRuntimeEntryPoint({ userMessage: "найди в 1С контрагента Группа СВК", deps: buildDeps([ { Counterparty: "Группа СВК", CounterpartyRef: "Ref-1" }, { Counterparty: "СВК Логистика", CounterpartyRef: "Ref-2" } ]) }); expect(result.entry_status).toBe("bridge_executed"); expect(result.discovery_attempted).toBe(true); expect(result.turn_input.semantic_data_need).toBe("entity discovery evidence"); expect(result.turn_input.turn_meaning_ref).toMatchObject({ asked_domain_family: "entity_resolution", asked_action_family: "search_business_entity", explicit_entity_candidates: ["Группа СВК"] }); expect(result.bridge?.bridge_status).toBe("answer_draft_ready"); expect(result.bridge?.pilot.pilot_scope).toBe("entity_resolution_search_v1"); expect(result.bridge?.pilot.executed_primitives).toEqual([ "search_business_entity", "resolve_entity_reference", "probe_coverage" ]); expect(result.bridge?.pilot.derived_entity_resolution).toMatchObject({ resolution_status: "resolved", resolved_entity: "Группа СВК", resolved_reference: "Ref-1" }); expect(result.bridge?.answer_draft.answer_mode).toBe("confirmed_with_bounded_inference"); }); it("runs the bridge again when the user clarifies one ambiguous entity-resolution candidate", async () => { const result = await runAssistantMcpDiscoveryRuntimeEntryPoint({ userMessage: "СВК-А", followupContext: { previous_discovery_pilot_scope: "entity_resolution_search_v1", previous_discovery_entity_resolution_status: "ambiguous", previous_discovery_entity_candidates: ["СВК", "СВК-А", "СВК-Б"], previous_discovery_entity_ambiguity_candidates: ["СВК-А", "СВК-Б"] }, deps: buildDeps([ { Counterparty: "СВК-А", CounterpartyRef: "Ref-1" }, { Counterparty: "СВК-Б", CounterpartyRef: "Ref-2" } ]) }); expect(result.entry_status).toBe("bridge_executed"); expect(result.discovery_attempted).toBe(true); expect(result.turn_input.source_signal).toBe("followup_context"); expect(result.turn_input.semantic_data_need).toBe("entity discovery evidence"); expect(result.turn_input.turn_meaning_ref).toMatchObject({ asked_domain_family: "entity_resolution", asked_action_family: "search_business_entity", explicit_entity_candidates: ["СВК-А"] }); expect(result.bridge?.pilot.pilot_scope).toBe("entity_resolution_search_v1"); expect(result.bridge?.pilot.executed_primitives).toEqual([ "search_business_entity", "resolve_entity_reference", "probe_coverage" ]); expect(result.bridge?.pilot.derived_entity_resolution).toMatchObject({ resolution_status: "resolved", resolved_entity: "СВК-А", resolved_reference: "Ref-1" }); }); it("chains an ordinal ambiguity clarification directly into value-flow execution", async () => { const result = await runAssistantMcpDiscoveryRuntimeEntryPoint({ userMessage: "второй вариант, сколько получили за 2020 год", followupContext: { previous_discovery_pilot_scope: "entity_resolution_search_v1", previous_discovery_entity_resolution_status: "ambiguous", previous_discovery_entity_candidates: ["СВК", "СВК-А", "СВК-Б"], previous_discovery_entity_ambiguity_candidates: ["СВК-А", "СВК-Б"] }, deps: buildDeps([ { Period: "2020-01-15T00:00:00", Amount: 1200, Counterparty: "СВК-Б" }, { Period: "2020-02-20T00:00:00", Amount: 800, Counterparty: "СВК-Б" } ]) }); expect(result.entry_status).toBe("bridge_executed"); expect(result.discovery_attempted).toBe(true); expect(result.turn_input.source_signal).toBe("followup_context"); expect(result.turn_input.semantic_data_need).toBe("counterparty value-flow evidence"); expect(result.turn_input.turn_meaning_ref).toMatchObject({ asked_domain_family: "counterparty_value", asked_action_family: "turnover", explicit_entity_candidates: ["СВК-Б"], explicit_date_scope: "2020" }); expect(result.bridge?.pilot.pilot_scope).toBe("counterparty_value_flow_query_movements_v1"); expect(result.bridge?.pilot.derived_value_flow).toMatchObject({ counterparty: "СВК-Б", period_scope: "2020", total_amount: 2000 }); }); it("chains an ordinal ambiguity clarification directly into document evidence execution", async () => { const result = await runAssistantMcpDiscoveryRuntimeEntryPoint({ userMessage: "первый вариант, покажи документы за 2020 год", followupContext: { previous_discovery_pilot_scope: "entity_resolution_search_v1", previous_discovery_entity_resolution_status: "ambiguous", previous_discovery_entity_candidates: ["СВК", "СВК-А", "СВК-Б"], previous_discovery_entity_ambiguity_candidates: ["СВК-А", "СВК-Б"] }, deps: buildDeps([{ Period: "2020-03-12T00:00:00", Counterparty: "СВК-А", Registrar: "Doc-1" }]) }); expect(result.entry_status).toBe("bridge_executed"); expect(result.discovery_attempted).toBe(true); expect(result.turn_input.source_signal).toBe("followup_context"); expect(result.turn_input.semantic_data_need).toBe("document evidence"); expect(result.turn_input.turn_meaning_ref).toMatchObject({ asked_domain_family: "documents", asked_action_family: "list_documents", explicit_entity_candidates: ["СВК-А"], explicit_date_scope: "2020" }); expect(result.bridge?.pilot.pilot_scope).toBe("counterparty_document_evidence_query_documents_v1"); expect(result.bridge?.answer_draft.answer_mode).toBe("confirmed_with_bounded_inference"); }); });