feat(webui): add initial webui with websocket chat flow
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
/** Truncate the first user message into a chat title. */
|
||||
export function deriveTitle(preview: string | undefined, fallback: string): string {
|
||||
if (!preview) return fallback;
|
||||
const oneLine = preview.replace(/\s+/g, " ").trim();
|
||||
if (!oneLine) return fallback;
|
||||
return oneLine.length > 60 ? `${oneLine.slice(0, 57)}…` : oneLine;
|
||||
}
|
||||
|
||||
/** Loose ISO-or-epoch parser; returns ``null`` for missing/invalid input. */
|
||||
function parseDate(value: string | number | null | undefined): Date | null {
|
||||
if (value === null || value === undefined || value === "") return null;
|
||||
const d = new Date(value);
|
||||
return Number.isNaN(d.getTime()) ? null : d;
|
||||
}
|
||||
|
||||
const RELATIVE_THRESHOLDS: [number, Intl.RelativeTimeFormatUnit][] = [
|
||||
[60, "second"],
|
||||
[60, "minute"],
|
||||
[24, "hour"],
|
||||
[7, "day"],
|
||||
[4.345, "week"],
|
||||
[12, "month"],
|
||||
[Number.POSITIVE_INFINITY, "year"],
|
||||
];
|
||||
|
||||
const RTF = new Intl.RelativeTimeFormat(undefined, { numeric: "auto" });
|
||||
|
||||
export function relativeTime(value: string | number | null | undefined): string {
|
||||
const date = parseDate(value);
|
||||
if (!date) return "";
|
||||
let delta = (date.getTime() - Date.now()) / 1000;
|
||||
for (const [step, unit] of RELATIVE_THRESHOLDS) {
|
||||
if (Math.abs(delta) < step) {
|
||||
return RTF.format(Math.round(delta), unit);
|
||||
}
|
||||
delta /= step;
|
||||
}
|
||||
return RTF.format(Math.round(delta), "year");
|
||||
}
|
||||
|
||||
export function fmtDateTime(value: string | number | null | undefined): string {
|
||||
const date = parseDate(value);
|
||||
return date ? date.toLocaleString() : "";
|
||||
}
|
||||
Reference in New Issue
Block a user