const MAX_TITLE = 72; export function isAutoGeneratedSessionLabel(label: string, key: string): boolean { const L = (label || "").trim(); if (!L) return true; if (L === key) return true; if (/^unsaved$/i.test(L)) return true; if (/^cwd-/i.test(L)) return true; if (/^session$/i.test(L)) return true; if (/^\d{4}-\d{2}-\d{2}[T\s]/.test(L)) return true; if (/^\d{4}\/\d{2}\/\d{2}/.test(L)) return true; if (/^\d{10,13}$/.test(L)) return true; return false; } export function titleFromUserText(text: string): string | null { const one = text.replace(/\s+/g, " ").trim(); if (!one) return null; const line = one.split("\n")[0].trim(); if (!line) return null; return line.length > MAX_TITLE ? line.slice(0, MAX_TITLE) + "…" : line; } export function pickSessionDisplayLabel(opts: { key: string; label?: string; firstUserMessage?: string | null; }): string { const first = opts.firstUserMessage?.trim(); if (first) return first; const label = (opts.label || "").trim(); if (label && !isAutoGeneratedSessionLabel(label, opts.key)) return label; return label || opts.key; } export function firstUserMessageFromJsonlLines(lines: string[]): string | null { for (const line of lines) { const trimmed = line.trim(); if (!trimmed) continue; try { const rec = JSON.parse(trimmed) as { kind?: string; eventName?: string; detail?: { text?: string }; summary?: string; }; if (rec.kind !== "pi_event" || rec.eventName !== "input") continue; if (typeof rec.detail?.text === "string") { const t = titleFromUserText(rec.detail.text); if (t) return t; } const sum = rec.summary || ""; const m = sum.match(/^input\s+(.+?)\s+\([^)]+\)\s*$/); if (m?.[1]) { const t = titleFromUserText(m[1].replace(/…$/, "")); if (t) return t; } } catch { /* skip */ } } return null; }