NODEDC_1C/llm_normalizer/backend/tests/assistantMcpDiscoveryRuntim...

95 lines
3.9 KiB
TypeScript
Raw 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, vi } from "vitest";
import { runAssistantMcpDiscoveryRuntimeBridge } from "../src/services/assistantMcpDiscoveryRuntimeBridge";
function buildDeps(rows: Array<Record<string, unknown>>, 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
}))
};
}
describe("assistant MCP discovery runtime bridge", () => {
it("composes planner, pilot executor, and answer draft without wiring the hot runtime", async () => {
const result = await runAssistantMcpDiscoveryRuntimeBridge({
turnMeaning: {
asked_domain_family: "counterparty_lifecycle",
asked_action_family: "activity_duration",
explicit_entity_candidates: ["SVK"]
},
deps: buildDeps([{ Период: "2020-01-15T00:00:00", Регистратор: "CP_CUSTOMER_ACTIVITY_FIRST" }])
});
expect(result.schema_version).toBe("assistant_mcp_discovery_runtime_bridge_v1");
expect(result.bridge_status).toBe("answer_draft_ready");
expect(result.hot_runtime_wired).toBe(false);
expect(result.pilot.mcp_execution_performed).toBe(true);
expect(result.answer_draft.answer_mode).toBe("confirmed_with_bounded_inference");
expect(result.business_fact_answer_allowed).toBe(true);
expect(result.user_facing_response_allowed).toBe(true);
expect(result.reason_codes).toContain("runtime_bridge_not_wired_to_hot_assistant_answer");
});
it("keeps missing scope as clarification and does not authorize a business fact answer", async () => {
const result = await runAssistantMcpDiscoveryRuntimeBridge({
turnMeaning: {
asked_domain_family: "counterparty_value",
asked_action_family: "turnover",
explicit_entity_candidates: ["SVK"]
},
deps: buildDeps([])
});
expect(result.bridge_status).toBe("needs_clarification");
expect(result.requires_user_clarification).toBe(true);
expect(result.pilot.mcp_execution_performed).toBe(false);
expect(result.business_fact_answer_allowed).toBe(false);
expect(result.answer_draft.next_step_line).toContain("Уточните контрагента");
});
it("keeps document-ready plans bounded when the pilot finds no confirmed rows", async () => {
const result = await runAssistantMcpDiscoveryRuntimeBridge({
turnMeaning: {
asked_domain_family: "document",
asked_action_family: "documents",
explicit_entity_candidates: ["SVK"]
},
deps: buildDeps([])
});
expect(result.bridge_status).toBe("checked_sources_only");
expect(result.hot_runtime_wired).toBe(false);
expect(result.pilot.pilot_scope).toBe("counterparty_document_evidence_query_documents_v1");
expect(result.pilot.mcp_execution_performed).toBe(true);
expect(result.business_fact_answer_allowed).toBe(false);
expect(result.reason_codes).toContain("runtime_bridge_status_checked_sources_only");
});
it("preserves the answer adapter boundary against internal mechanics leakage", async () => {
const result = await runAssistantMcpDiscoveryRuntimeBridge({
turnMeaning: {
asked_domain_family: "counterparty_lifecycle",
asked_action_family: "activity_duration",
explicit_entity_candidates: ["SVK"]
},
deps: buildDeps([{ Период: "2020-01-15T00:00:00", Регистратор: "CP_CUSTOMER_ACTIVITY_FIRST" }])
});
const userFacing = [
result.answer_draft.headline,
...result.answer_draft.confirmed_lines,
...result.answer_draft.inference_lines,
...result.answer_draft.unknown_lines,
...result.answer_draft.limitation_lines,
result.answer_draft.next_step_line ?? ""
].join("\n");
expect(userFacing).not.toContain("query_documents");
expect(userFacing).not.toContain("runtime_bridge");
expect(userFacing).not.toContain("primitive");
});
});