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

122 lines
4.2 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 {
runAssistantLivingChatAttemptRuntime,
type RunAssistantLivingChatAttemptRuntimeInput
} from "../src/services/assistantLivingChatAttemptRuntimeAdapter";
type TestResponse = { ok: boolean; llm: string };
function buildInput(
overrides: Partial<RunAssistantLivingChatAttemptRuntimeInput<TestResponse>> = {}
): RunAssistantLivingChatAttemptRuntimeInput<TestResponse> {
return {
sessionId: "asst-1",
userMessage: "контрагенты со сверкой",
sessionItems: [{ role: "user", text: "контекст" }],
modeDecision: { mode: "chat", reason: "living_chat_signal_detected" },
sessionScope: {
knownOrganizations: [],
selectedOrganization: null,
activeOrganization: null
},
addressRuntimeMeta: null,
traceIdFactory: () => "chat-trace-1",
toNonEmptyString: (value: unknown) => (typeof value === "string" && value.trim() ? value.trim() : null),
mergeKnownOrganizations: (values: string[]) => values,
hasAssistantDataScopeMetaQuestionSignal: () => false,
shouldHandleAsAssistantCapabilityMetaQuery: () => false,
hasDestructiveDataActionSignal: () => false,
hasDangerOrCoercionSignal: () => false,
hasOperationalAdminActionRequestSignal: () => false,
hasOrganizationFactLookupSignal: () => false,
hasOrganizationFactFollowupSignal: () => false,
shouldEmitOrganizationSelectionReply: () => false,
hasAssistantCapabilityQuestionSignal: () => false,
resolveDataScopeProbe: async () => null,
applyScriptGuard: (text: string) => ({ text, applied: false, reason: null }),
applyGroundingGuard: (payload: { chatText: string }) => ({
text: payload.chatText,
applied: false,
reason: null
}),
buildAssistantSafetyRefusalReply: () => "safety",
buildAssistantDataScopeContractReply: () => "scope",
buildAssistantOrganizationFactBoundaryReply: () => "boundary",
buildAssistantDataScopeSelectionReply: () => "selection",
buildAssistantOperationalBoundaryReply: () => "operational",
buildAssistantCapabilityContractReply: () => "capability",
appendItem: () => {},
getSession: () => ({
session_id: "asst-1",
updated_at: "",
items: [],
investigation_state: null
}),
persistSession: () => {},
cloneConversation: (items: unknown[]) => items,
logEvent: () => {},
messageIdFactory: () => "msg-1",
nowIso: () => "2026-04-10T00:00:00.000Z",
payload: {
llmProvider: "openai",
apiKey: "key",
model: "gpt-5",
baseUrl: "http://localhost",
temperature: 0.2,
maxOutputTokens: 300
},
chatClient: {
chat: async () => ({ outputText: "chat-output" })
},
loadAssistantCanonExcerpt: () => "canon",
sanitizeOutgoingAssistantText: (value: unknown, fallback = "fallback") => {
const text = String(value ?? "").trim();
return text || fallback;
},
defaultModel: "gpt-5",
defaultBaseUrl: "http://localhost",
defaultApiKey: "key",
...overrides
};
}
describe("assistant living chat attempt runtime adapter", () => {
it("wires llm runtime output into living handler execute callback", async () => {
const runLivingChatLlm = vi.fn(async () => "llm-answer");
const runLivingChatHandler = vi.fn(async (input) => {
const llm = await input.executeLlmChat();
return { ok: true, llm };
});
const response = await runAssistantLivingChatAttemptRuntime(
buildInput({
runLivingChatHandler,
runLivingChatLlm
})
);
expect(runLivingChatHandler).toHaveBeenCalledTimes(1);
expect(runLivingChatLlm).toHaveBeenCalledWith(
expect.objectContaining({
userMessage: "контрагенты со сверкой"
})
);
expect(response).toEqual({ ok: true, llm: "llm-answer" });
});
it("returns null when delegated handler returns null", async () => {
const runLivingChatLlm = vi.fn(async () => "llm-answer");
const runLivingChatHandler = vi.fn(async () => null);
const response = await runAssistantLivingChatAttemptRuntime(
buildInput({
runLivingChatHandler,
runLivingChatLlm
})
);
expect(response).toBeNull();
expect(runLivingChatLlm).not.toHaveBeenCalled();
});
});