90 lines
3.3 KiB
TypeScript
90 lines
3.3 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
||
import { createAssistantLivingModePolicy } from "../src/services/assistantLivingModePolicy";
|
||
|
||
function buildPolicy() {
|
||
return createAssistantLivingModePolicy({
|
||
featureAssistantLivingChatRouterV1: true,
|
||
compactWhitespace: (text: string) => text.replace(/\s+/g, " ").trim(),
|
||
repairAddressMojibake: (text: string) => text,
|
||
toNonEmptyString: (value: unknown) => {
|
||
if (value === null || value === undefined) {
|
||
return null;
|
||
}
|
||
const text = String(value).trim();
|
||
return text.length > 0 ? text : null;
|
||
},
|
||
normalizeOrganizationScopeValue: (value: unknown) => {
|
||
if (value === null || value === undefined) {
|
||
return null;
|
||
}
|
||
const text = String(value).trim().replace(/^"+|"+$/g, "").replace(/^'+|'+$/g, "");
|
||
return text.length > 0 ? text : null;
|
||
},
|
||
hasReferentialPointer: (text: string) => /(same thing|that one|this one)/i.test(text.toLowerCase()),
|
||
hasSmallTalkSignal: (text: string) => /(thanks|thank you|hello|hi)\b/i.test(text.toLowerCase()),
|
||
hasAssistantCapabilityQuestionSignal: (text: string) =>
|
||
/(?:what can you do|capabilities|features)/i.test(text),
|
||
hasOperationalAdminActionRequestSignal: (text: string) =>
|
||
/(?:install|update|delete\s+database|drop\s+database)/i.test(text),
|
||
resolveProviderExecutionState: (input: { useMock?: unknown }) => ({
|
||
living_mode_forced_deep: Boolean(input?.useMock),
|
||
living_mode_forced_reason: Boolean(input?.useMock) ? "mock_mode_keeps_deep_pipeline" : null
|
||
})
|
||
});
|
||
}
|
||
|
||
describe("assistantLivingModePolicy", () => {
|
||
it("detects explicit recap wording as memory signal even when selected-object words are present", () => {
|
||
const policy = buildPolicy();
|
||
|
||
expect(
|
||
policy.hasConversationMemoryRecallFollowupSignal("а ты помнишь, что мы по этой позиции уже выяснили?")
|
||
).toBe(true);
|
||
});
|
||
|
||
it("routes casual small-talk to chat mode", () => {
|
||
const policy = buildPolicy();
|
||
|
||
const decision = policy.resolveLivingAssistantModeDecision({
|
||
userMessage: "hello",
|
||
addressLaneTriggered: false,
|
||
useMock: false,
|
||
predecomposeMode: "unsupported",
|
||
predecomposeModeConfidence: "low"
|
||
});
|
||
|
||
expect(decision.mode).toBe("chat");
|
||
expect(decision.reason).toBe("living_chat_signal_detected");
|
||
});
|
||
|
||
it("keeps explicit inventory question in deep mode", () => {
|
||
const policy = buildPolicy();
|
||
|
||
const decision = policy.resolveLivingAssistantModeDecision({
|
||
userMessage: "show warehouse inventory for 2020",
|
||
addressLaneTriggered: false,
|
||
useMock: false,
|
||
predecomposeMode: "unsupported",
|
||
predecomposeModeConfidence: "low"
|
||
});
|
||
|
||
expect(decision.mode).toBe("deep_analysis");
|
||
expect(decision.reason).toBe("strong_data_signal_detected");
|
||
});
|
||
|
||
it("keeps deep pipeline in mock mode via provider execution policy", () => {
|
||
const policy = buildPolicy();
|
||
|
||
const decision = policy.resolveLivingAssistantModeDecision({
|
||
userMessage: "hello",
|
||
addressLaneTriggered: false,
|
||
useMock: true,
|
||
predecomposeMode: "unsupported",
|
||
predecomposeModeConfidence: "low"
|
||
});
|
||
|
||
expect(decision.mode).toBe("deep_analysis");
|
||
expect(decision.reason).toBe("mock_mode_keeps_deep_pipeline");
|
||
});
|
||
});
|