import type { OpenAI } from 'openai'; export type HumanReadableToLookbackMinutesReturnType = { minutes: number; _raw?: string; }; const MINUTE = 1; const HOUR = 60; const DAY = 24 * HOUR; const COMMON_MAP: Record = { '1h': HOUR, '1 hour': HOUR, 'one hour': HOUR, '2h': 2 * HOUR, '2 hours': 2 * HOUR, '6h': 6 * HOUR, '6 hours': 6 * HOUR, '12h': 12 * HOUR, '12 hours': 12 * HOUR, '24h': 24 * HOUR, '24 hours': 24 * HOUR, '1d': DAY, '1 day': DAY, day: DAY, '30m': 30, '30 minutes': 30, '15m': 15, '15 minutes': 15, }; /** * Lightweight local parser for common patterns: "X minutes/hours/days" */ export function parseLookbackToMinutesLocal(text: string): number | null { const t = text.toLowerCase().trim(); if (t in COMMON_MAP) return COMMON_MAP[t]; // e.g. "last 6 hours", "6h", "6 hours", "90 minutes", "1 day" const re = /(last\s+)?(\d+(?:\.\d+)?)\s*(minutes?|mins?|m|hours?|hrs?|h|days?|d)\b/; const m = t.match(re); if (!m) return null; const value = parseFloat(m[2]); const unit = m[3]; if (Number.isNaN(value)) return null; if (/^m(in(ute)?s?)?$/.test(unit)) return Math.round(value * MINUTE); if (/^h((ou)?rs?)?$/.test(unit)) return Math.round(value * HOUR); if (/^d(ays?)?$/.test(unit)) return Math.round(value * DAY); return null; } /** * Uses OpenAI to convert a human prompt like "last 6 hours" into minutes */ export async function humanReadableToLookbackMinutes( openai: OpenAI, prompt: string, ): Promise { const local = parseLookbackToMinutesLocal(prompt); if (local !== null) { return { minutes: local, _raw: 'local' }; } const resp = await openai.chat.completions.create({ model: 'gpt-4o-mini', temperature: 0, messages: [ { role: 'system', content: 'Convert the user text describing a time window into a single integer number of minutes. Return ONLY the integer. Examples: "6 hours" => 360; "90 minutes" => 90; "1 day" => 1440.', }, { role: 'user', content: prompt }, ], }); const content = resp.choices?.[0]?.message?.content?.trim(); if (!content) throw new Error('OpenAI returned empty content'); const minutes = parseInt(content.replace(/[^0-9]/g, ''), 10); if (!Number.isFinite(minutes) || minutes <= 0) { throw new Error('Failed to parse minutes'); } return { minutes, _raw: content }; }