import type { EpisodeConfig, StructuredScript } from "../types"; const FORMAT_GUIDANCE: Record = { SOLO: "A single host speaking directly to the listener. Use only the host speaker.", INTERVIEW: "A host interviewing a guest. Alternate naturally between host questions and guest answers.", MULTI_HOST: "A panel of co-hosts in lively conversation. Distribute lines across all speakers and let them react to each other.", }; /** Roughly 150 spoken words per minute → target word budget for the whole episode. */ function wordBudget(minutes: number): number { return Math.round(minutes * 150); } export function buildScriptMessages(config: EpisodeConfig) { const speakerList = config.speakers .map((s) => `- key "${s.speakerKey}" = ${s.displayName}`) .join("\n"); const system = [ "You are an expert podcast scriptwriter and showrunner.", "You write natural, engaging, spoken-word scripts that sound great when read aloud by AI voices.", "Avoid stage directions, sound-effect notes, and parentheticals — output only spoken dialogue.", "Return STRICT JSON only, matching the requested schema. Do not include markdown fences.", ].join(" "); const user = [ `Write a complete podcast episode script in ${config.language}.`, "", `Topic: ${config.topic}`, `Tone: ${config.tone}`, `Format: ${config.format} — ${FORMAT_GUIDANCE[config.format]}`, config.audience ? `Target audience: ${config.audience}` : "", `Approximate length: ${config.targetLengthMin} minutes (~${wordBudget( config.targetLengthMin )} words total).`, "", "Speakers (use ONLY these keys in `speakerKey`):", speakerList, "", "Structure the episode into 3–6 sections (e.g. intro, main segments, outro).", "Each section has a short title and a list of turns. Each turn is one speaker's spoken line.", "", "Return JSON with this exact shape:", `{ "title": "string — a catchy episode title", "sections": [ { "id": "kebab-case-id", "title": "string", "turns": [ { "speakerKey": "host", "text": "spoken line..." } ] } ] }`, ] .filter(Boolean) .join("\n"); return [ { role: "system" as const, content: system }, { role: "user" as const, content: user }, ]; } export function buildSectionMessages( config: EpisodeConfig, script: StructuredScript, sectionId: string ) { const section = script.sections.find((s) => s.id === sectionId); const speakerList = config.speakers.map((s) => `"${s.speakerKey}"=${s.displayName}`).join(", "); const system = "You are an expert podcast scriptwriter. Rewrite a single section of an existing episode, keeping the same speakers, tone, and language. Return STRICT JSON for just that one section."; const user = [ `Episode title: ${script.title}`, `Tone: ${config.tone}. Language: ${config.language}. Speakers: ${speakerList}.`, "", `Rewrite the section titled "${section?.title ?? sectionId}" (id "${sectionId}") to be fresh and engaging while serving the same purpose in the episode.`, "", "Return JSON with this exact shape:", `{ "id": "${sectionId}", "title": "string", "turns": [ { "speakerKey": "host", "text": "..." } ] }`, ].join("\n"); return [ { role: "system" as const, content: system }, { role: "user" as const, content: user }, ]; }