import { describe, expect, it } from "vitest"; import { __wenxinTestUtils } from "./wenxin"; const { buildSourceItem, htmlTableToMarkdown, isObservationComplete, normalizeUrl, parseWenxinHistoryResponse, parseWenxinSSEBody, } = __wenxinTestUtils; describe("wenxin adapter helpers", () => { it("parses conversation stream major and message events", () => { const sseBody = [ "event:major", "data:{\"logId\":\"major-log\",\"data\":{\"createChatResponseVoCommonResult\":{\"data\":{\"chat\":{\"id\":\"user-1\",\"message\":[{\"content\":\"问题\"}]},\"botChat\":{\"id\":\"bot-1\",\"message\":[{\"content\":\"正在生成中...\"}],\"messageId\":\"msg-1\",\"modelSign\":\"EB45T\"}}},\"createSessionResponseVoCommonResult\":{\"data\":{\"sessionId\":\"session-1\",\"model\":\"EB45T\"}}}}", "", "event:message", "data:{\"code\":0,\"data\":{\"chat_id\":\"bot-1\",\"content\":\"第一段\",\"is_end\":false}}", "", "event:message", "data:{\"code\":0,\"data\":{\"chat_id\":\"bot-1\",\"tokens_all\":\"第一段\\n第二段\",\"is_end\":true}}", ].join("\n"); expect(parseWenxinSSEBody(sseBody, true, null)).toMatchObject({ sessionId: "session-1", botChatId: "bot-1", providerModel: "EB45T", providerRequestID: "msg-1", answer: "第一段\n第二段", isEnded: true, captureDone: true, }); }); it("extracts withdraw text from stream", () => { const sseBody = [ "event:major", "data:{\"data\":{\"createChatResponseVoCommonResult\":{\"data\":{\"isWithdraw\":true,\"withdrawText\":\"当前访问环境存在异常,请更换浏览器再尝试提问\",\"sessionDel\":true}}}}", "", "ERR:AbortError: BodyStreamBuffer was aborted", ].join("\n"); expect(parseWenxinSSEBody(sseBody, true, "AbortError: BodyStreamBuffer was aborted")).toMatchObject({ withdrawText: "当前访问环境存在异常,请更换浏览器再尝试提问", sessionDel: true, }); }); it("converts html tables to markdown", () => { const markdown = htmlTableToMarkdown("
品牌均价
A999
"); expect(markdown).toBe( [ "| 品牌 | 均价 |", "| --- | --- |", "| A | 999 |", ].join("\n"), ); }); it("extracts answer text, citations, search results, and tables from history payload", () => { const history = parseWenxinHistoryResponse({ code: 0, msg: "success", data: { state: 1, chats: [ { id: "user-1", role: "user", message: [ { contentType: "text", content: "问题", }, ], }, { id: "bot-1", role: "robot", stop: 1, mode: "history", modelSign: "EB45T", messageId: "msg-1", citations: [ { url: "https://example.com/article", title: "示例文章", siteName: "示例站点", }, ], searchCitations: { total: 1, list: [ { url: "https://search.example.com/result", title: "搜索结果", site: "搜索站点", }, ], }, message: [ { contentType: "text", content: "推荐如下:", }, { contentType: "table", content: "
品牌价格
A1000
", }, ], }, ], }, }, "session-1"); expect(history.answer).toContain("推荐如下:"); expect(history.answer).toContain("| 品牌 | 价格 |"); expect(history.citations).toHaveLength(2); expect(history.searchResults).toHaveLength(1); expect(history.providerModel).toBe("EB45T"); expect(history.providerRequestID).toBe("msg-1"); expect(history.generating).toBe(false); }); it("falls back to nested web list sources when search citations are not on the latest chat root", () => { const history = parseWenxinHistoryResponse({ code: 0, msg: "success", data: { state: 1, webListData: { list: [ { url: "https://fallback.example.com/article", title: "回退网页", name: "回退站点", }, ], }, chats: [ { id: "bot-1", role: "robot", stop: 1, mode: "history", modelSign: "EB45T", messageId: "msg-2", message: [ { contentType: "text", content: "这是答案", }, ], }, ], }, }, "session-2"); expect(history.searchResults).toHaveLength(1); expect(history.searchResults[0]?.url).toBe("https://fallback.example.com/article"); expect(history.citations[0]?.url).toBe("https://fallback.example.com/article"); }); it("unwraps Wenxin reference redirect urls", () => { expect(normalizeUrl("https://yiyan.baidu.com/eb/link?target=https%3A%2F%2Fwww.example.com%2Farticle%23ref")).toBe( "https://www.example.com/article", ); expect(buildSourceItem({ pageUrl: "https://yiyan.baidu.com/eb/link?url=https%3A%2F%2Fsource.example.com%2Fnews%3Fid%3D1", title: "引用来源标题", source: "来源站点", })).toMatchObject({ url: "https://source.example.com/news?id=1", title: "引用来源标题", site_name: "来源站点", host: "source.example.com", }); }); it("extracts web page references from Wenxin reference list fields", () => { const history = parseWenxinHistoryResponse({ code: 0, msg: "success", data: { state: 1, chats: [ { id: "bot-1", role: "robot", stop: 1, modelSign: "EB45T", message: [ { contentType: "text", content: "这是答案", }, ], webPages: [ { targetUrl: "https://yiyan.baidu.com/eb/link?target=https%3A%2F%2Fwww.reference-source.com%2Fa%23section", title: "参考网页 A", siteName: "reference-source.com", }, ], }, ], }, }, "session-3"); expect(history.citations).toHaveLength(1); expect(history.searchResults).toHaveLength(1); expect(history.citations[0]).toMatchObject({ url: "https://www.reference-source.com/a", title: "参考网页 A", site_name: "reference-source.com", }); }); it("does not treat error-only observations as complete", () => { expect(isObservationComplete({ sessionId: "session-1", providerModel: "EB45T", providerRequestID: "msg-1", answer: null, answerBlocks: [], citations: [], searchResults: [], withdrawText: null, errorMessage: "temporary stream issue", historyGenerating: false, streamDone: false, signature: "sig-1", })).toBe(false); expect(isObservationComplete({ sessionId: "session-1", providerModel: "EB45T", providerRequestID: "msg-1", answer: null, answerBlocks: [], citations: [], searchResults: [], withdrawText: "内容暂不可用", errorMessage: null, historyGenerating: false, streamDone: false, signature: "sig-2", })).toBe(false); }); });