import { describe, expect, it } from "vitest"; import { buildAssistantConversationItem, buildDeepAnswerArtifacts } from "../src/services/assistantDeepResponseAssembler"; describe("assistant deep response assembler", () => { it("strips technical tail and builds fallback answer structure when missing in composition", () => { const artifacts = buildDeepAnswerArtifacts({ safeAssistantReplyBase: "Короткий ответ\n\ndebug_payload_json: {\"x\":1}", featureContractsV11: true, featureAnswerPolicyV11: true, compositionAnswerStructureV11: null, coverageReport: { requirements_total: 1, requirements_covered: 1, requirements_uncovered: [], requirements_partially_covered: [], clarification_needed_for: [], out_of_scope_requirements: [] }, groundingCheck: { status: "grounded", route_subject_match: true, missing_requirements: [], reasons: [], why_included_summary: [], selection_reason_summary: [] }, retrievalResults: [] }); expect(artifacts.safeAssistantReply).toBe("Короткий ответ"); expect(artifacts.answerStructureV11?.schema_version).toBe("answer_structure_v1_1"); }); it("uses provided composition answer structure and creates assistant conversation item", () => { const provided = { schema_version: "answer_structure_v1_1", answer_summary: "sum", direct_answer: "direct", mechanism_block: { status: "grounded" as const, mechanism_notes: [], limitation_reason_codes: [] }, evidence_block: { evidence_ids: [], mechanism_notes: [], coverage_note: "ok" }, uncertainty_block: { open_uncertainties: [], limitations: [] }, next_step_block: { recommended_actions: [], clarification_questions: [] } }; const artifacts = buildDeepAnswerArtifacts({ safeAssistantReplyBase: "Готово", featureContractsV11: true, featureAnswerPolicyV11: true, compositionAnswerStructureV11: provided as any, coverageReport: { requirements_total: 1, requirements_covered: 1, requirements_uncovered: [], requirements_partially_covered: [], clarification_needed_for: [], out_of_scope_requirements: [] }, groundingCheck: { status: "grounded", route_subject_match: true, missing_requirements: [], reasons: [], why_included_summary: [], selection_reason_summary: [] }, retrievalResults: [] }); expect(artifacts.answerStructureV11).toEqual(provided); const item = buildAssistantConversationItem({ messageId: "msg-1", sessionId: "asst-1", text: artifacts.safeAssistantReply, replyType: "factual", traceId: "trace-1", debug: { trace_id: "trace-1", prompt_version: "normalizer_v2_0_2", schema_version: "normalized_query_v2_0_2", fallback_type: "none", route_summary: null, fragments: [], requirements_extracted: [], coverage_report: { requirements_total: 0, requirements_covered: 0, requirements_uncovered: [], requirements_partially_covered: [], clarification_needed_for: [], out_of_scope_requirements: [] }, routes: [], retrieval_status: [], retrieval_results: [], answer_grounding_check: { status: "no_grounded_answer", route_subject_match: false, missing_requirements: [], reasons: [], why_included_summary: [], selection_reason_summary: [] }, dropped_intent_segments: [], answer_structure_v11: null, investigation_state_snapshot: null, normalized: null } as any }); expect(item.message_id).toBe("msg-1"); expect(item.session_id).toBe("asst-1"); expect(item.reply_type).toBe("factual"); expect(item.text).toBe("Готово"); expect(typeof item.created_at).toBe("string"); }); });