import { z } from "zod"; import { openai, SCRIPT_MODEL } from "./openai"; import type { TokenUsage } from "./types"; const seasonSchema = z.object({ title: z.string().min(1), description: z.string().min(1), episodes: z .array(z.object({ title: z.string().min(1), topic: z.string().min(1), summary: z.string().min(1) })) .min(1), }); export type SeasonPlan = z.infer; export async function planSeason(input: { theme: string; count: number; tone: string; audience?: string; language: string; }): Promise<{ plan: SeasonPlan; usage: TokenUsage }> { const res = await openai().chat.completions.create({ model: SCRIPT_MODEL, messages: [ { role: "system", content: "You are a podcast showrunner planning a cohesive season. Return STRICT JSON: { \"title\": string, \"description\": string, \"episodes\": [{ \"title\": string, \"topic\": string, \"summary\": string }] }.", }, { role: "user", content: `Plan a ${input.count}-episode podcast season about: ${input.theme}. Tone: ${input.tone}. ${input.audience ? `Audience: ${input.audience}.` : ""} Language: ${input.language}. Give the season a title and short description, then ${input.count} episodes, each with a catchy title, a specific topic to cover, and a one-sentence summary.`, }, ], response_format: { type: "json_object" }, temperature: 0.85, }); const plan = seasonSchema.parse(JSON.parse(res.choices[0]?.message?.content ?? "{}")); return { plan, usage: { inputTokens: res.usage?.prompt_tokens ?? 0, outputTokens: res.usage?.completion_tokens ?? 0, }, }; }