ГЛОБАЛЬНЫЙ РЕФАКТОРИНГ АРХИТЕКТУРЫ - Рефакторинг этапов 2.612.64 - вынос mapper для assistantAddressLaneResponseAttemptRuntimeAdapter и для assistantLivingChatAttemptRuntimeAdapter / сборка входов для living chat attempt в отдельный builder (LLM + handler)
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { buildAssistantAddressLaneResponseRuntimeInput } from "../src/services/assistantAddressLaneResponseRuntimeInputBuilder";
|
||||
|
||||
function buildInput(overrides: Record<string, unknown> = {}) {
|
||||
return {
|
||||
sessionId: "asst-1",
|
||||
userMessage: "where is settlement tail",
|
||||
effectiveAddressUserMessage: "where is settlement tail for Org A",
|
||||
addressLane: {
|
||||
reply_text: "address reply",
|
||||
reply_type: "factual_with_explanation",
|
||||
debug: {}
|
||||
},
|
||||
carryoverMeta: { previousReplyType: "partial_coverage" },
|
||||
llmPreDecomposeMeta: { mode: "supported", confidence: "high" },
|
||||
knownOrganizations: ["Org A"],
|
||||
activeOrganization: "Org A",
|
||||
sanitizeOutgoingAssistantText: vi.fn((value: unknown, fallback = "") => {
|
||||
const text = String(value ?? "").trim();
|
||||
return text || fallback;
|
||||
}),
|
||||
buildAddressDebugPayload: vi.fn(() => ({})),
|
||||
buildAddressFollowupOffer: vi.fn(() => null),
|
||||
mergeKnownOrganizations: vi.fn((values: string[]) => values),
|
||||
toNonEmptyString: vi.fn((value: unknown) =>
|
||||
typeof value === "string" && value.trim().length > 0 ? value.trim() : null
|
||||
),
|
||||
appendItem: vi.fn(),
|
||||
getSession: vi.fn(),
|
||||
persistSession: vi.fn(),
|
||||
cloneConversation: vi.fn((items: unknown[]) => items),
|
||||
logEvent: vi.fn(),
|
||||
messageIdFactory: vi.fn(() => "msg-1"),
|
||||
...overrides
|
||||
} as any;
|
||||
}
|
||||
|
||||
describe("assistant address lane response runtime input builder", () => {
|
||||
it("maps lane-response fields into runtime input", () => {
|
||||
const runtimeInput = buildAssistantAddressLaneResponseRuntimeInput(buildInput());
|
||||
|
||||
expect(runtimeInput.sessionId).toBe("asst-1");
|
||||
expect(runtimeInput.effectiveAddressUserMessage).toBe("where is settlement tail for Org A");
|
||||
expect(runtimeInput.knownOrganizations).toEqual(["Org A"]);
|
||||
expect(runtimeInput.carryoverMeta).toEqual({ previousReplyType: "partial_coverage" });
|
||||
expect(runtimeInput.llmPreDecomposeMeta).toEqual({ mode: "supported", confidence: "high" });
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,83 @@
|
||||
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),
|
||||
shouldEmitOrganizationSelectionReply: vi.fn(() => false),
|
||||
hasAssistantCapabilityQuestionSignal: vi.fn(() => false),
|
||||
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"),
|
||||
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"
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user