import { describe, expect, it, vi } from "vitest"; import { runAssistantDeepTurnResponseRuntime } from "../src/services/assistantDeepTurnResponseRuntimeAdapter"; function buildBaseInput(overrides: Record = {}) { return { featureInvestigationStateV1: true, featureContractsV11: true, featureAnswerPolicyV11: true, sessionId: "asst-1", questionId: "msg-q1", userMessage: "question", normalized: { trace_id: "trace-1", prompt_version: "normalizer_v2_0_2", schema_version: "normalized_query_v2_0_2", normalized: { schema_version: "normalized_query_v2_0_2" } }, normalizedQuestion: "normalized-question", routeSummary: { mode: "deterministic_v2", decisions: [] as any[] }, executionPlan: [], requirementExtractionRequirements: [], coverageEvaluationRequirements: [], coverageReport: {}, groundingCheck: { status: "no_grounded_answer", reasons: [] }, retrievalCalls: [], retrievalResultsRaw: [], retrievalResults: [], questionTypeClass: "single_fact_lookup", companyAnchors: {}, runtimeAnalysisContext: {}, businessScopeResolution: {}, temporalGuard: {}, polarityAudit: {}, claimAnchorAudit: {}, targetedEvidenceAudit: {}, evidenceAdmissibilityGateAudit: {}, rbpLiveRouteAudit: {}, faLiveRouteAudit: {}, groundedAnswerEligibilityGuard: {}, followupStateUsage: null, followupApplied: false, composition: { reply_type: "factual", assistant_reply: "assistant answer" }, previousInvestigationState: null, addressRuntimeMetaForDeep: null, extractDroppedIntentSegments: () => [], buildDebugRoutes: () => [], extractExecutionState: () => [], sanitizeReply: (value: string) => value, persistInvestigationState: () => {}, messageIdFactory: () => "msg-a1", appendItem: () => {}, getSession: () => ({ session_id: "asst-1", items: [] }), persistSession: () => {}, cloneConversation: () => [], logEvent: () => {}, ...overrides } as any; } describe("assistant deep turn response runtime adapter", () => { it("wires packaging output into deep finalization", () => { const runPackagingRuntime = vi.fn(() => ({ messageId: "msg-a1", investigationStateSnapshot: null, droppedIntentSegments: [], analysisContextForContract: null, routesForDebug: [], resolvedExecutionState: [], safeAssistantReplyBase: "base", safeAssistantReply: "safe-reply", debug: { trace_id: "trace-1" }, assistantItem: { message_id: "msg-a1", session_id: "asst-1", role: "assistant", text: "safe-reply", reply_type: "factual", created_at: "2026-04-10T00:00:00.000Z", trace_id: "trace-1", debug: null }, deepAnalysisLogDetails: { info: "ok" } })); const responsePayload = { ok: true, session_id: "asst-1", conversation: [], debug: { trace_id: "trace-1" } }; const runFinalizeDeepTurn = vi.fn(() => ({ response: responsePayload })); const runtime = runAssistantDeepTurnResponseRuntime( buildBaseInput({ runPackagingRuntime, runFinalizeDeepTurn }) ); expect(runPackagingRuntime).toHaveBeenCalledTimes(1); expect(runFinalizeDeepTurn).toHaveBeenCalledWith( expect.objectContaining({ sessionId: "asst-1", assistantReply: "safe-reply", replyType: "factual" }) ); expect(runtime.response).toEqual(responsePayload); expect(runtime.debug).toMatchObject({ trace_id: "trace-1", mcp_discovery_response_applied: false }); }); it("passes feature flags and followup flags into packaging stage", () => { const runPackagingRuntime = vi.fn(() => ({ messageId: "msg-a1", investigationStateSnapshot: null, droppedIntentSegments: [], analysisContextForContract: null, routesForDebug: [], resolvedExecutionState: [], safeAssistantReplyBase: "base", safeAssistantReply: "safe-reply", debug: {}, assistantItem: { message_id: "msg-a1", session_id: "asst-1", role: "assistant", text: "safe-reply", reply_type: "factual", created_at: "2026-04-10T00:00:00.000Z", trace_id: "trace-1", debug: null }, deepAnalysisLogDetails: {} })); runAssistantDeepTurnResponseRuntime( buildBaseInput({ featureInvestigationStateV1: false, followupApplied: true, runPackagingRuntime, runFinalizeDeepTurn: () => ({ response: { ok: true, session_id: "asst-1", conversation: [], debug: null } }) }) ); expect(runPackagingRuntime).toHaveBeenCalledWith( expect.objectContaining({ featureInvestigationStateV1: false, followupApplied: true }) ); }); it("can replace a bad deep partial answer with a guarded MCP discovery candidate", () => { const runPackagingRuntime = vi.fn(() => ({ messageId: "msg-a1", investigationStateSnapshot: null, droppedIntentSegments: [], analysisContextForContract: null, routesForDebug: [], resolvedExecutionState: [], safeAssistantReplyBase: "bad-base", safeAssistantReply: "bad deep partial answer", debug: { trace_id: "trace-1" }, assistantItem: { message_id: "msg-a1", session_id: "asst-1", role: "assistant", text: "bad deep partial answer", reply_type: "partial_coverage", created_at: "2026-04-10T00:00:00.000Z", trace_id: "trace-1", debug: null }, deepAnalysisLogDetails: {} })); const runFinalizeDeepTurn = vi.fn((input) => ({ response: { ok: true, session_id: "asst-1", assistant_reply: input.assistantReply, reply_type: input.replyType, conversation_item: input.assistantItem, conversation: [], debug: input.debug } })); const runtime = runAssistantDeepTurnResponseRuntime( buildBaseInput({ composition: { reply_type: "partial_coverage" }, addressRuntimeMetaForDeep: { mcpDiscoveryRuntimeEntryPoint: { schema_version: "assistant_mcp_discovery_runtime_entry_point_v1", policy_owner: "assistantMcpDiscoveryRuntimeEntryPoint", entry_status: "bridge_executed", hot_runtime_wired: false, discovery_attempted: true, turn_input: { should_run_discovery: true }, bridge: { bridge_status: "answer_draft_ready", user_facing_response_allowed: true, business_fact_answer_allowed: true, requires_user_clarification: false, answer_draft: { answer_mode: "confirmed_with_bounded_inference", headline: "Discovery answer", confirmed_lines: ["Confirmed fact"], inference_lines: [], unknown_lines: [], limitation_lines: [], next_step_line: null } }, reason_codes: [] } }, runPackagingRuntime, runFinalizeDeepTurn }) ); expect(runtime.response.assistant_reply).toContain("Discovery answer"); expect(runtime.debug?.mcp_discovery_response_applied).toBe(true); expect(runFinalizeDeepTurn).toHaveBeenCalledWith( expect.objectContaining({ assistantReply: expect.stringContaining("Discovery answer"), replyType: "partial_coverage", assistantItem: expect.objectContaining({ text: expect.stringContaining("Discovery answer") }) }) ); }); });