50 lines
1.8 KiB
TypeScript
50 lines
1.8 KiB
TypeScript
import { isGenericSessionTitle } from "@/lib/agent-reply";
|
|
|
|
function hanLength(value: string): number {
|
|
return Array.from(value.replace(/\s+/g, "")).length;
|
|
}
|
|
|
|
function clipHan(value: string, maxChars: number): string {
|
|
const characters = Array.from(value);
|
|
return characters.length > maxChars ? characters.slice(0, maxChars).join("") : value;
|
|
}
|
|
|
|
const BIRTH_STAMP = /\d{4}年\d{1,2}月(?:\d{1,2}日)?|\d{1,2}:\d{2}/;
|
|
const DATED_ENTRY_TITLE = /^\d{1,2}月\d{1,2}日\s*·\s*(?:今日节奏|生时校正)$/;
|
|
|
|
export function sanitizeSessionTitle(raw: string): string | null {
|
|
if (/[\r\n]/.test(raw)) return null;
|
|
const stripped = raw
|
|
.replace(/[“”"‘’'「」『』《》]/g, "")
|
|
.replace(/[。..!?!?、,,;;::]+$/u, "")
|
|
.replace(/\s+/g, " ")
|
|
.trim();
|
|
if (!stripped) return null;
|
|
if (hanLength(stripped) < 2) return null;
|
|
if (isGenericSessionTitle(stripped)) return null;
|
|
if (BIRTH_STAMP.test(stripped)) return null;
|
|
const clipped = clipHan(stripped, 14);
|
|
if (hanLength(clipped) < 6) return null;
|
|
return clipped;
|
|
}
|
|
|
|
export function isAutoDerivedSessionTitle(title: string): boolean {
|
|
const text = title.replace(/\s+/g, " ").trim();
|
|
if (!text) return true;
|
|
if (isGenericSessionTitle(text)) return true;
|
|
if (DATED_ENTRY_TITLE.test(text)) return true;
|
|
if (/…$|\.{3}$/.test(text)) return true;
|
|
return false;
|
|
}
|
|
|
|
export function shouldGenerateSessionTitle(
|
|
session: { title?: string | null; sessionType?: string | null },
|
|
storedHistory: readonly unknown[],
|
|
): boolean {
|
|
if (storedHistory.length > 0) return false;
|
|
if (session.sessionType === "birth_time_rectification") return false;
|
|
const title = typeof session.title === "string" ? session.title : "";
|
|
if (DATED_ENTRY_TITLE.test(title.replace(/\s+/g, " ").trim())) return false;
|
|
return isAutoDerivedSessionTitle(title);
|
|
}
|