import type { BoxBrainMemoryStore, DateTimeInput, MandatoryConversationContext, MemorySpace, PersonaMessage, ScheduledAvailabilitySnapshot, } from "./types"; import { addUtcDays, dateKeysAround, startOfUtcDay, toIso } from "./schedule"; export function formatMessageHistory(input: { personaName: string; messages: PersonaMessage[]; }): string { return input.messages .map((message) => { const sender = message.sender === "persona" ? input.personaName : "user"; return `${sender}@${toIso(message.time)}: ${message.content}`; }) .join("\n"); } export function conversationInstruction(baseSystemPrompt?: string): string { const parts = [ ...(baseSystemPrompt === undefined ? [] : [baseSystemPrompt]), "You are controlling the persona, not a generic assistant.", "Use the send_message tool conceptually: return one or more outgoing messages.", "Unless the persona strongly prefers otherwise, keep each outgoing message to at most one sentence.", "Prefer short, natural, chat-like wording and allow splitting one thought into multiple messages.", 'If mandatory memory says "기억이 없음", the persona may naturally wonder about missing context instead of pretending to remember.', ]; return parts.join("\n"); } export async function buildMandatoryConversationContext(input: { persona: MemorySpace; now: DateTimeInput; memory: BoxBrainMemoryStore; messages: PersonaMessage[]; availability: ScheduledAvailabilitySnapshot; }): Promise { const now = startOfUtcDay(input.now); const from = addUtcDays(now, -1).toISOString(); const to = addUtcDays(now, 2).toISOString(); const scheduleEntries = await input.memory.listScheduleEntries( input.persona.id, from, to, ); const personaAndUserFacts = await input.memory.findFacts(input.persona.id, [ "persona", input.persona.displayName, "user", ]); const memorySummary = personaAndUserFacts.length === 0 ? "기억이 없음" : personaAndUserFacts.map((fact) => `- ${fact.statement}`).join("\n"); return { formattedMessageHistory: formatMessageHistory({ personaName: input.persona.displayName, messages: input.messages, }), conversationWindowLabel: `Required conversation window: yesterday/today. Schedule dates: ${dateKeysAround(input.now).join(", ")}.`, memorySummary, personaAndUserFacts, scheduleEntries, availability: input.availability, }; }