Files
KrisHD_AI/public/app/regeneration.js
T

53 lines
2.5 KiB
JavaScript

import {stream} from "./api.js";
import {updateReasoning, finishReasoning} from "./reasoning.js";
import {appendSources} from "./webSearch.js";
// Keep the original nodes (including action handlers) until a committed answer arrives.
export async function regenerateInline({card, scroller, endpoint, payload, renderContent, complete}) {
const original = [...card.childNodes];
const status = document.createElement("div");
status.className = "loading-shell";
status.setAttribute("role", "status");
status.textContent = "Generating...";
const body = document.createElement("div");
body.className = "msg-content streaming-content";
let committed = false;
const update = operation => {
const bottom = card.getBoundingClientRect().bottom;
const viewport = scroller.getBoundingClientRect();
const follow = bottom >= viewport.top && Math.abs(bottom - viewport.bottom) < 100;
operation();
if (follow) scroller.scrollTop += card.getBoundingClientRect().bottom - bottom;
};
// Anchor to this response, including when a long old answer collapses.
update(() => card.replaceChildren(original[0].cloneNode(true), status, body));
card.setAttribute("aria-busy", "true");
try {
await stream(endpoint, payload, {
onStatus: data => update(() => {
status.textContent = data.status === "searching" ? "Searching the web..."
: data.status === "analyzing" ? "Analyzing attachments..." : "Generating...";
if ("sources" in data) {
card.querySelector(".msg-sources")?.remove();
appendSources(card, data.sources);
}
}),
onThinking: ({fullThinking}) => update(() => updateReasoning(card, fullThinking, true)),
onChunk: ({fullReply}) => update(() => {
status.hidden = Boolean(fullReply);
if (fullReply) finishReasoning(card);
renderContent(body, fullReply);
}),
onError: ({error}) => { throw new Error(error || "Unable to regenerate message."); },
onDone: ({message}) => {
if (!message) throw new Error("Missing regenerated response.");
update(() => complete(message));
committed = true;
}
});
} finally {
if (!committed) update(() => card.replaceChildren(...original));
card.removeAttribute("aria-busy");
}
}