export interface ConversationTurn { role: "user" | "assistant"; text: string; speakerId?: string; speakerName?: string; createdAt: number; } export interface UserUtterance { speakerId: string; speakerName: string; text: string; } export class ConversationMemory { private readonly turns: ConversationTurn[] = []; constructor(private readonly maxTurns: number) {} addUserTurn(utterance: UserUtterance): void { this.turns.push({ role: "user", text: utterance.text, speakerId: utterance.speakerId, speakerName: utterance.speakerName, createdAt: Date.now(), }); this.trim(); } addAssistantTurn(text: string): void { this.turns.push({ role: "assistant", text, createdAt: Date.now(), }); this.trim(); } clear(): void { this.turns.splice(0, this.turns.length); } recentTurns(): ConversationTurn[] { return [...this.turns]; } buildPrompt(currentUtterance: UserUtterance): string { const recent = this.turns .slice(-this.maxTurns) .map((turn) => { if (turn.role === "assistant") { return `[assistant]\n${turn.text}`; } return `[user speaker_id=${turn.speakerId ?? "unknown"} speaker_name=${turn.speakerName ?? "unknown"}]\n${turn.text}`; }) .join("\n\n"); const historyBlock = recent.length > 0 ? recent : "(이전 대화 없음)"; return [ "최근 대화:", historyBlock, "", "이번 발화:", `[user speaker_id=${currentUtterance.speakerId} speaker_name=${currentUtterance.speakerName}]`, currentUtterance.text, ].join("\n"); } private trim(): void { const overflow = this.turns.length - this.maxTurns; if (overflow > 0) { this.turns.splice(0, overflow); } } }