Initial commit: PodcastYes — AI podcast platform

This commit is contained in:
Leon Serfaty
2026-06-07 03:58:32 -04:00
commit 155507f21a
151 changed files with 19826 additions and 0 deletions
+48
View File
@@ -0,0 +1,48 @@
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<typeof seasonSchema>;
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,
},
};
}