import { describe, expect, it } from "vitest"; import { createAssistantBoundaryPolicy } from "../src/services/assistantBoundaryPolicy"; function createPolicy() { return createAssistantBoundaryPolicy({ activeMcpChannel: "default", normalizeOrganizationScopeValue: (value: unknown) => { if (value === null || value === undefined) { return null; } const text = String(value ?? "") .replace(/\\/g, "") .replace(/([А-Яа-яA-Za-z])"([А-Яа-яA-Za-z])/gu, "$1в$2") .trim(); return text.length > 0 ? text : null; }, toNonEmptyString: (value: unknown) => { if (value === null || value === undefined) { return null; } const text = String(value ?? "").trim(); return text.length > 0 ? text : null; }, hasOrganizationFactLookupSignal: (message: string) => /возраст|дата регистрации/i.test(message) }); } describe("assistantBoundaryPolicy", () => { it("builds deterministic data-scope reply for single organization", () => { const policy = createPolicy(); const reply = policy.buildAssistantDataScopeContractReply({ status: "resolved", channel: "finance", organizations: ["ООО Альтернатива Плюс"] }); expect(reply).toContain("Сейчас доступна организация"); expect(reply).toContain("ООО Альтернатива Плюс"); expect(reply).not.toContain("MCP"); expect(reply.toLowerCase()).not.toContain("read-only"); }); it("normalizes noisy organization labels in data-scope reply", () => { const policy = createPolicy(); const reply = policy.buildAssistantDataScopeContractReply({ status: "resolved", channel: "default", organizations: ['ООО \\Альтернати"а Плюс\\', 'ООО \\Лайс"уд\\'] }); expect(reply).toContain('ООО Альтернатива Плюс'); expect(reply).toContain('ООО Лайсвуд'); expect(reply).not.toContain('\\"'); expect(reply).not.toContain("\\"); }); it("strips unexpected CJK fragments from live chat reply", () => { const policy = createPolicy(); const guarded = policy.applyLivingChatScriptGuard( "Прошу прощения, но я не могу продолжать этот разговор. 随时关注。", "че как" ); expect(guarded.applied).toBe(true); expect(guarded.reason).toBe("unexpected_cjk_fragment_stripped"); expect(guarded.text).toContain("Прошу прощения"); expect(/[\u3400-\u9FFF\uF900-\uFAFF]/u.test(guarded.text)).toBe(false); }); it("blocks ungrounded organization fact answer with deterministic boundary reply", () => { const policy = createPolicy(); const guarded = policy.applyLivingChatGroundingGuard({ userMessage: "какой возраст у альтернативы?", chatText: "Для ООО Альтернатива Плюс дата регистрации 01.07.2015, возраст 8 лет.", organization: "ООО Альтернатива Плюс" }); expect(guarded.applied).toBe(true); expect(guarded.reason).toBe("organization_fact_without_live_source_blocked"); expect(guarded.text.toLowerCase()).toContain("не буду называть"); expect(guarded.text).not.toContain("01.07.2015"); }); });