NODEDC_1C/llm_normalizer/backend/tests/assistantLivingChatAttemptR...

87 lines
3.9 KiB
TypeScript

import { describe, expect, it, vi } from "vitest";
import {
buildAssistantLivingChatHandlerRuntimeInput,
buildAssistantLivingChatLlmRuntimeInput
} from "../src/services/assistantLivingChatAttemptRuntimeInputBuilder";
describe("assistant living chat attempt runtime input builder", () => {
it("builds living-chat llm runtime input", () => {
const runtimeInput = buildAssistantLivingChatLlmRuntimeInput({
userMessage: "hello",
sessionItems: [{ role: "user", text: "ctx" }],
payload: { llmProvider: "openai" } as any,
chatClient: {} as any,
loadAssistantCanonExcerpt: vi.fn(() => "canon"),
sanitizeOutgoingAssistantText: vi.fn((value: unknown) => String(value ?? "")),
defaultModel: "gpt-5",
defaultBaseUrl: "http://localhost",
defaultApiKey: "key"
});
expect(runtimeInput.userMessage).toBe("hello");
expect(runtimeInput.sessionItems).toEqual([{ role: "user", text: "ctx" }]);
expect(runtimeInput.defaultModel).toBe("gpt-5");
expect(runtimeInput.defaultBaseUrl).toBe("http://localhost");
expect(runtimeInput.defaultApiKey).toBe("key");
});
it("builds living-chat handler runtime input with execute callback", async () => {
const executeLlmChat = vi.fn(async () => "llm-answer");
const runtimeInput = buildAssistantLivingChatHandlerRuntimeInput({
sessionId: "asst-1",
userMessage: "hello",
sessionItems: [],
modeDecision: { mode: "chat", reason: "living_chat_signal_detected" },
sessionScope: { knownOrganizations: [], selectedOrganization: null, activeOrganization: null },
addressRuntimeMeta: null,
traceIdFactory: vi.fn(() => "chat-1"),
toNonEmptyString: vi.fn((value: unknown) =>
typeof value === "string" && value.trim().length > 0 ? value.trim() : null
),
mergeKnownOrganizations: vi.fn((values: string[]) => values),
hasAssistantDataScopeMetaQuestionSignal: vi.fn(() => false),
shouldHandleAsAssistantCapabilityMetaQuery: vi.fn(() => false),
hasDestructiveDataActionSignal: vi.fn(() => false),
hasDangerOrCoercionSignal: vi.fn(() => false),
hasOperationalAdminActionRequestSignal: vi.fn(() => false),
hasOrganizationFactLookupSignal: vi.fn(() => false),
hasOrganizationFactFollowupSignal: vi.fn(() => false),
hasLivingChatSignal: vi.fn(() => false),
shouldEmitOrganizationSelectionReply: vi.fn(() => false),
hasAssistantCapabilityQuestionSignal: vi.fn(() => false),
resolveOrganizationSelectionFromMessage: vi.fn(() => null),
resolveDataScopeProbe: vi.fn(async () => null),
executeLlmChat,
applyScriptGuard: vi.fn((text: string) => ({ text, applied: false, reason: null })),
applyGroundingGuard: vi.fn((payload: { chatText: string }) => ({
text: payload.chatText,
applied: false,
reason: null
})),
buildAssistantSafetyRefusalReply: vi.fn(() => "safety"),
buildAssistantDataScopeContractReply: vi.fn(() => "scope"),
buildAssistantProactiveOrganizationOfferReply: vi.fn(() => "offer"),
buildAssistantOrganizationFactBoundaryReply: vi.fn(() => "boundary"),
buildAssistantDataScopeSelectionReply: vi.fn(() => "selection"),
buildAssistantOperationalBoundaryReply: vi.fn(() => "operational"),
buildAssistantCapabilityContractReply: vi.fn(() => "capability"),
appendItem: vi.fn(),
getSession: vi.fn(),
persistSession: vi.fn(),
cloneConversation: vi.fn((items: unknown[]) => items),
logEvent: vi.fn(),
messageIdFactory: vi.fn(() => "msg-1"),
nowIso: vi.fn(() => "2026-04-11T00:00:00.000Z"),
runLivingChatRuntime: vi.fn(async () => null),
finalizeLivingChatTurn: vi.fn()
});
await runtimeInput.executeLlmChat();
expect(executeLlmChat).toHaveBeenCalledTimes(1);
expect(runtimeInput.modeDecision).toEqual({
mode: "chat",
reason: "living_chat_signal_detected"
});
});
});