АРЧ АП11 - Вынести living-chat boundary policy из assistantService в отдельный модуль

This commit is contained in:
2026-04-16 09:21:48 +03:00
parent d7c4eb781a
commit 606654641b
5 changed files with 541 additions and 14 deletions
@@ -0,0 +1,68 @@
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 ?? "").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("MCP-канале `finance`");
expect(reply).toContain("ООО Альтернатива Плюс");
expect(reply.toLowerCase()).toContain("read-only");
});
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");
});
});