mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-23 08:58:11 -07:00
101 lines
3.1 KiB
JavaScript
101 lines
3.1 KiB
JavaScript
import { renderMarkdown } from "../../markdown.js";
|
|
import { formatDuration } from "../../timing.js";
|
|
import { createAskChart } from "./chart/index.js";
|
|
|
|
/** @typedef {"user" | "assistant"} MessageRole */
|
|
|
|
/**
|
|
* @param {HTMLElement} content
|
|
* @param {MessageRole} role
|
|
* @param {string} text
|
|
*/
|
|
export function setMessageContent(content, role, text) {
|
|
if (role === "assistant") renderMarkdown(content, text);
|
|
else content.textContent = text;
|
|
}
|
|
|
|
/**
|
|
* @param {MessageRole} role
|
|
* @param {string} text
|
|
* @param {Object} [metadata]
|
|
* @param {import("../../storage.js").StoredArtifact[]} [metadata.artifacts]
|
|
* @param {number} [metadata.elapsedMs]
|
|
* @param {import("../../timing.js").ResponseStep[]} [metadata.steps]
|
|
*/
|
|
export function createAskMessage(role, text, metadata = {}) {
|
|
const { artifacts = [], elapsedMs, steps = [] } = metadata;
|
|
const item = document.createElement("li");
|
|
const label = document.createElement("strong");
|
|
const content = document.createElement("div");
|
|
const responseSteps = role === "assistant"
|
|
? document.createElement("ol")
|
|
: undefined;
|
|
const responseTime = role === "assistant"
|
|
? document.createElement("small")
|
|
: undefined;
|
|
|
|
/** @param {import("../../storage.js").StoredArtifact[]} nextArtifacts */
|
|
function setArtifacts(nextArtifacts) {
|
|
item.querySelectorAll(":scope > [data-ask-chart]").forEach((chart) => {
|
|
chart.remove();
|
|
});
|
|
const charts = nextArtifacts
|
|
.filter((artifact) => artifact.type === "chart")
|
|
.map(createAskChart);
|
|
|
|
if (responseSteps) responseSteps.before(...charts);
|
|
else item.append(...charts);
|
|
}
|
|
|
|
/** @param {import("../../timing.js").ResponseStep[]} nextSteps */
|
|
function setSteps(nextSteps) {
|
|
if (!responseSteps) return;
|
|
|
|
responseSteps.replaceChildren(...nextSteps.map((step) => {
|
|
const item = document.createElement("li");
|
|
const name = document.createElement("span");
|
|
const duration = document.createElement("time");
|
|
|
|
name.textContent = step.label;
|
|
if (step.elapsedMs === undefined) item.dataset.active = "";
|
|
else duration.textContent = formatDuration(step.elapsedMs);
|
|
item.append(name, duration);
|
|
return item;
|
|
}));
|
|
responseSteps.hidden = !nextSteps.length;
|
|
}
|
|
|
|
/** @param {number | undefined} nextElapsedMs */
|
|
function setElapsed(nextElapsedMs) {
|
|
if (!responseTime) return;
|
|
|
|
const visible =
|
|
typeof nextElapsedMs === "number" &&
|
|
Number.isFinite(nextElapsedMs) &&
|
|
nextElapsedMs >= 0;
|
|
responseTime.hidden = !visible;
|
|
responseTime.textContent = visible
|
|
? `${formatDuration(nextElapsedMs)} total`
|
|
: "";
|
|
}
|
|
|
|
item.dataset.role = role;
|
|
label.append(role === "user" ? "You" : "Assistant");
|
|
setMessageContent(content, role, text);
|
|
item.append(label, content);
|
|
if (responseSteps) {
|
|
responseSteps.dataset.responseSteps = "";
|
|
item.append(responseSteps);
|
|
}
|
|
if (responseTime) {
|
|
responseTime.dataset.responseTime = "";
|
|
responseTime.title = "Response time";
|
|
item.append(responseTime);
|
|
}
|
|
setArtifacts(artifacts);
|
|
setSteps(steps);
|
|
setElapsed(elapsedMs);
|
|
|
|
return { item, content, setArtifacts, setSteps, setElapsed };
|
|
}
|