1import { assistantCitationsToPlainText } from "@t3tools/shared/assistantCitations";
2import { truncate } from "@t3tools/shared/String";
3
4export interface ThreadTitleSeedInput {
5 readonly text: string;
6 readonly attachments: ReadonlyArray<{ readonly name: string }>;
7 readonly fallbackLabels?: ReadonlyArray<string | null | undefined>;
8}
9
10function normalizeTitleSeed(value: string): string {
11 return assistantCitationsToPlainText(value).trim().replace(/\s+/gu, " ");
12}
13
14export function deriveThreadTitleSeed(input: ThreadTitleSeedInput): string {
15 const text = normalizeTitleSeed(input.text);
16 if (text.length > 0) {
17 return truncate(text);
18 }
19
20 const attachmentName = normalizeTitleSeed(input.attachments[0]?.name ?? "");
21 if (attachmentName.length > 0) {
22 return truncate(`Image: ${attachmentName}`);
23 }
24
25 for (const label of input.fallbackLabels ?? []) {
26 const normalized = normalizeTitleSeed(label ?? "");
27 if (normalized.length > 0) {
28 return truncate(normalized);
29 }
30 }
31
32 return "New thread";
33}