119 lines
4.1 KiB
TypeScript
119 lines
4.1 KiB
TypeScript
import { describe, expect, it, vi } from "vitest";
|
|
import { tryHandleAssistantLivingChatRuntime } from "../src/services/assistantLivingChatHandlerRuntimeAdapter";
|
|
|
|
function buildInput(overrides: Record<string, unknown> = {}) {
|
|
return {
|
|
sessionId: "asst-1",
|
|
userMessage: "question",
|
|
sessionItems: [],
|
|
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: unknown[]) => values.map((v) => String(v)),
|
|
hasAssistantDataScopeMetaQuestionSignal: () => false,
|
|
shouldHandleAsAssistantCapabilityMetaQuery: () => false,
|
|
hasDestructiveDataActionSignal: () => false,
|
|
hasDangerOrCoercionSignal: () => false,
|
|
hasOperationalAdminActionRequestSignal: () => false,
|
|
hasOrganizationFactLookupSignal: () => false,
|
|
hasOrganizationFactFollowupSignal: () => false,
|
|
hasLivingChatSignal: () => true,
|
|
shouldEmitOrganizationSelectionReply: () => false,
|
|
hasAssistantCapabilityQuestionSignal: () => false,
|
|
resolveDataScopeProbe: async () => null,
|
|
executeLlmChat: async () => "chat answer",
|
|
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 } as any),
|
|
persistSession: () => {},
|
|
cloneConversation: (items: any[]) => items,
|
|
logEvent: vi.fn(),
|
|
messageIdFactory: () => "msg-1",
|
|
nowIso: () => "2026-04-10T00:00:00.000Z",
|
|
...overrides
|
|
} as any;
|
|
}
|
|
|
|
describe("assistant living chat handler runtime adapter", () => {
|
|
it("returns finalized response when runtime is handled", async () => {
|
|
const runLivingChatRuntime = vi.fn(async () => ({
|
|
handled: true,
|
|
chatText: "chat",
|
|
debug: { trace_id: "chat-1" }
|
|
}));
|
|
const finalizeLivingChatTurn = vi.fn(() => ({
|
|
response: { ok: true, lane: "chat" }
|
|
}));
|
|
|
|
const response = await tryHandleAssistantLivingChatRuntime(
|
|
buildInput({
|
|
runLivingChatRuntime,
|
|
finalizeLivingChatTurn
|
|
})
|
|
);
|
|
|
|
expect(runLivingChatRuntime).toHaveBeenCalledTimes(1);
|
|
expect(finalizeLivingChatTurn).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
assistantReply: "chat",
|
|
replyType: "factual_with_explanation"
|
|
})
|
|
);
|
|
expect(response).toEqual({ ok: true, lane: "chat" });
|
|
});
|
|
|
|
it("returns null when runtime is not handled", async () => {
|
|
const finalizeLivingChatTurn = vi.fn();
|
|
const response = await tryHandleAssistantLivingChatRuntime(
|
|
buildInput({
|
|
runLivingChatRuntime: async () => ({
|
|
handled: false,
|
|
chatText: "",
|
|
debug: null
|
|
}),
|
|
finalizeLivingChatTurn
|
|
})
|
|
);
|
|
|
|
expect(response).toBeNull();
|
|
expect(finalizeLivingChatTurn).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("logs warn and returns null on runtime error", async () => {
|
|
const logEvent = vi.fn();
|
|
const response = await tryHandleAssistantLivingChatRuntime(
|
|
buildInput({
|
|
runLivingChatRuntime: async () => {
|
|
throw new Error("boom");
|
|
},
|
|
logEvent
|
|
})
|
|
);
|
|
|
|
expect(response).toBeNull();
|
|
expect(logEvent).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
level: "warn",
|
|
message: "assistant_living_chat_failed_fallback_to_deep"
|
|
})
|
|
);
|
|
});
|
|
});
|