import { openai, defaultModel, serviceOptions, parseWithRetry } from '../agent.js'; import type { InterpreterOutput, MediaType } from '../types/agents.js'; import { z } from 'zod'; import { zodTextFormat } from 'openai/helpers/zod'; const InterpreterSchema = z.object({ liked: z.array(z.string()), disliked: z.array(z.string()), themes: z.array(z.string()), character_preferences: z.array(z.string()), tone: z.array(z.string()), avoid: z.array(z.string()), requirements: z.array(z.string()) }); interface InterpreterInput { main_prompt: string; liked_shows: string; disliked_shows: string; themes: string; media_type: MediaType; feedback_context?: string; } export async function runInterpreter(input: InterpreterInput): Promise { const mediaLabel = input.media_type === 'movie' ? 'movie' : 'TV show'; const feedbackSection = input.feedback_context ? `\n\nUser Feedback Context (incorporate into preferences):\n${input.feedback_context}` : ''; const response = await parseWithRetry(() => openai.responses.parse({ model: defaultModel, temperature: 0.2, ...serviceOptions, text: { format: zodTextFormat(InterpreterSchema, "preferences") }, instructions: `You are a ${mediaLabel} preference interpreter. Transform raw user input into structured, normalized preferences. Rules: - Extract implicit preferences from the main prompt - Normalize terminology (e.g. "spy" → "espionage", "cop show" → "police procedural") - Detect and resolve contradictions (prefer explicit over implicit) - Do NOT assume anything not stated or clearly implied - Be specific and concrete, not vague - For "requirements": capture explicit hard requirements the user stated that recommendations must satisfy — things like "must be from the 2000s onward", "must have subtitles", "must feature a female lead". Leave empty if no such constraints were stated.`, input: `Main prompt: ${input.main_prompt} Liked ${mediaLabel}s: ${input.liked_shows || '(none)'} Disliked ${mediaLabel}s: ${input.disliked_shows || '(none)'} Themes and requirements: ${input.themes || '(none)'}${feedbackSection}`, })); return (response.output_parsed as InterpreterOutput) ?? { liked: [], disliked: [], themes: [], character_preferences: [], tone: [], avoid: [], requirements: [] }; }