import assert from "node:assert/strict" import test from "node:test" import { NextRequest } from "next/server" import { POST } from "@/app/api/chat/route" type CapturedPayload = { model: string messages: Array<{ role: string; content: string }> } const ORIGINAL_FETCH = globalThis.fetch const ORIGINAL_XAI_KEY = process.env.XAI_API_KEY function buildVisitor(intent: string) { return { name: "Taylor", phone: "(801) 555-1000", email: "taylor@example.com", intent, serviceTextConsent: true, marketingTextConsent: false, consentVersion: "sms-consent-v1-2026-03-26", consentCapturedAt: "2026-03-25T00:00:00.000Z", consentSourcePage: "/contact-us", } } function buildRequest(message: string, intent = "Manuals") { return new NextRequest("http://localhost/api/chat", { method: "POST", headers: { "content-type": "application/json", }, body: JSON.stringify({ pathname: "/manuals", sessionId: "test-session", visitor: buildVisitor(intent), messages: [{ role: "user", content: message }], }), }) } async function runChatRouteWithSpy( message: string, intent = "Manuals" ): Promise<{ response: Response; payload: CapturedPayload }> { process.env.XAI_API_KEY = "test-xai-key" let capturedPayload: CapturedPayload | null = null globalThis.fetch = (async (_input: RequestInfo | URL, init?: RequestInit) => { capturedPayload = JSON.parse(String(init?.body || "{}")) as CapturedPayload return new Response( JSON.stringify({ choices: [ { message: { content: "Mock Jessica reply.", }, }, ], }), { status: 200, headers: { "content-type": "application/json", }, } ) }) as typeof fetch const response = await POST(buildRequest(message, intent)) assert.ok(capturedPayload) return { response, payload: capturedPayload } } test.afterEach(() => { globalThis.fetch = ORIGINAL_FETCH if (typeof ORIGINAL_XAI_KEY === "string") { process.env.XAI_API_KEY = ORIGINAL_XAI_KEY } else { delete process.env.XAI_API_KEY } }) test("chat route includes grounded manual context for RVV alias lookups", async () => { const { response, payload } = await runChatRouteWithSpy( "RVV 660 service manual" ) assert.equal(response.status, 200) assert.equal( payload.messages.some( (message) => message.role === "system" && message.content.includes("Manual knowledge context:") ), true ) assert.equal( payload.messages.some( (message) => message.role === "system" && /Royal Vendors|660/i.test(message.content) ), true ) }) test("chat route resolves Narco alias lookups into manual context", async () => { const { payload } = await runChatRouteWithSpy("Narco bevmax not cooling") const manualContext = payload.messages.find( (message) => message.role === "system" && message.content.includes("Manual knowledge context:") ) assert.ok(manualContext) assert.match(manualContext.content, /Dixie-Narco|Narco/i) }) test("chat route low-confidence manual queries instruct Jessica to ask for brand model or photo", async () => { const { payload } = await runChatRouteWithSpy( "manual for flibbertigibbet machine" ) const manualContext = payload.messages.find( (message) => message.role === "system" && message.content.includes("Manual knowledge context:") ) assert.ok(manualContext) assert.match( manualContext.content, /brand on the front|model sticker|photo\/video/i ) }) test("chat route risky technical manual queries inject conservative safety context", async () => { const { payload } = await runChatRouteWithSpy( "Royal wiring diagram voltage manual", "Repairs" ) const systemPrompt = payload.messages[0]?.content || "" const manualContext = payload.messages.find( (message) => message.role === "system" && message.content.includes("Manual knowledge context:") ) assert.match( systemPrompt, /Do not provide step-by-step repair procedures, wiring guidance, voltage guidance/i ) assert.ok(manualContext) assert.match(manualContext.content, /technical or risky/i) }) test("chat route skips manuals retrieval for non-manual conversations", async () => { const { payload } = await runChatRouteWithSpy( "Can someone call me back about free placement?", "Free Placement" ) const systemMessages = payload.messages.filter( (message) => message.role === "system" ) assert.equal(systemMessages.length, 1) assert.equal( systemMessages.some((message) => message.content.includes("Manual knowledge context:") ), false ) })