(frame)
| 4540 | let doneReceived = false; |
| 4541 | |
| 4542 | const processFrame = (frame) => { |
| 4543 | if (!frame.trim()) return; |
| 4544 | const parsed = parseSseFrame(frame); |
| 4545 | if (!parsed) return; |
| 4546 | if (parsed.event === "error") throw new Error(parsed.data.error || ui().chat.streamFailed); |
| 4547 | if (parsed.event === "status" && !text) { |
| 4548 | answerTarget.innerHTML = `<p>${escapeHtml(parsed.data.text || ui().chat.generating)}</p>`; |
| 4549 | } |
| 4550 | if (parsed.event === "meta") { |
| 4551 | result = { ...result, ...parsed.data }; |
| 4552 | citations = normalizeCitations(parsed.data); |
| 4553 | const metaTarget = message.querySelector(".answer-meta"); |
| 4554 | if (metaTarget) metaTarget.outerHTML = renderAnswerMeta(parsed.data, citations); |
| 4555 | renderChatSources(citations); |
| 4556 | } |
| 4557 | if (parsed.event === "chunk") { |
| 4558 | text += parsed.data.text || ""; |
| 4559 | answerTarget.classList.remove("loading"); |
| 4560 | answerTarget.innerHTML = renderAnswerWithCitations(text, citations); |
| 4561 | $("chatThread").scrollTop = $("chatThread").scrollHeight; |
| 4562 | } |
| 4563 | if (parsed.event === "done") { |
| 4564 | doneReceived = true; |
| 4565 | result = { ...result, ...parsed.data }; |
| 4566 | text = parsed.data.text || text; |
| 4567 | citations = normalizeCitations(parsed.data); |
| 4568 | const metaTarget = message.querySelector(".answer-meta"); |
| 4569 | if (metaTarget) metaTarget.outerHTML = renderAnswerMeta(parsed.data, citations); |
| 4570 | answerTarget.classList.remove("loading"); |
| 4571 | answerTarget.innerHTML = renderAnswerWithCitations(text, citations); |
| 4572 | renderChatSources(citations); |
| 4573 | } |
| 4574 | }; |
| 4575 | |
| 4576 | while (true) { |
| 4577 | const { value, done } = await reader.read(); |
no test coverage detected