{"version":3,"file":"index.cjs","sources":["../../../src/ai/cron-expression.ts","../../../src/ai/lookback-window.ts"],"sourcesContent":["import type { OpenAI } from 'openai';\n\ntype OpenAIChatCompletionResponseType = OpenAI.Chat.Completions.ChatCompletion & {\n  _request_id?: string | null;\n};\n\nexport type ValidateHumanReadableCronExpressionPromptReturnType = {\n  isValid: boolean;\n  reason: string;\n  _completion: OpenAIChatCompletionResponseType;\n};\n\nconst model = 'gpt-4o-mini';\n\n/**\n * Validates if a human-readable prompt is related to generating cron expressions or scheduling tasks\n * @param openai - The OpenAI client\n * @param prompt - The human-readable prompt\n * @returns The validation result\n */\nexport async function validateHumanReadableCronExpressionPrompt(\n  openai: OpenAI,\n  prompt: string,\n): Promise<HumanReadableToCronExpressionReturnType> {\n  const response = await openai.chat.completions.create({\n    model,\n    messages: [\n      {\n        role: 'system',\n        content: `You are a validator that determines if a user's prompt is related to generating cron expressions or scheduling tasks.\n\n          Return a JSON object with two fields:\n          1. \"isValid\": boolean - true if the prompt is asking about creating a cron expression or scheduling, false otherwise. It should also be\n          false if the prompt is asking to generate an invalid cron expression.\n          2. \"reason\": string - a brief explanation of your decision\n\n          Examples of valid prompts:\n          - \"I need a cron job that runs every day at midnight\"\n          - \"every 15 minutes\"\n          - \"Every year\"\n          - \"every 50 minutes\"\n          - \"every hour\"\n          - \"every day at 2 AM\"\n\n          Examples of invalid prompts:\n          - \"What's the weather like today?\"\n          - \"Write me a poem about cats\"\n          - \"How do I make chocolate chip cookies?\"\n          `,\n      },\n      {\n        role: 'user',\n        content: prompt,\n      },\n    ],\n  });\n\n  const content = response.choices[0]?.message?.content;\n\n  if (!content) {\n    throw new Error('Failed to validate the prompt');\n  }\n\n  try {\n    // Parse the JSON response\n    const validation = JSON.parse(content);\n    return {\n      ...validation,\n      _completion: response,\n    };\n  } catch (error) {\n    throw new Error('Error parsing validation response');\n  }\n}\n\nexport type HumanReadableToCronExpressionReturnType = {\n  cronExpression: string;\n  _completion: OpenAIChatCompletionResponseType;\n};\n\n/**\n * Generates a cron expression from a human-readable prompt\n * @param openai - The OpenAI client\n * @param prompt - The human-readable prompt\n * @returns The cron expression\n */\nexport async function humanReadableToCronExpression(\n  openai: OpenAI,\n  prompt: string,\n): Promise<HumanReadableToCronExpressionReturnType> {\n  // Request the OpenAI API for the response without streaming\n  const response = await openai.chat.completions.create({\n    model,\n    temperature: 0,\n    messages: [\n      {\n        role: 'system',\n        content: `Below is text describing a cron expression.\n          Your goal is to:\n          - Convert the text to a valid cron expression.\n          - The cron expression you generate must be in 5-field format: minute hour day month dayOfWeek\n          - The cron expression must match this pattern: minute hour day month dayOfWeek\n          - Return only the generated cron expression and nothing else.\n\n          Here are some examples:\n          - Text: A cron that runs every hour\n          - Cron: 0 * * * *\n          - Text: A cron that runs every 12 hours\n          - Cron: 0 */12 * * *\n          - Text: A cron that runs every 30 minutes\n          - Cron: */30 * * * *\n          - Text: A cron that runs every day at 2 AM\n          - Cron: 0 2 * * *\n          - Text: A cron that runs every 50 minutes\n          - Cron: */50 * * * *\n          - Text: A cron that runs every week on Monday at 9 AM\n          - Cron: 0 9 * * 1`,\n      },\n      {\n        role: 'user',\n        content: prompt,\n      },\n    ],\n  });\n\n  // Validate the response\n  const content = response.choices[0]?.message?.content?.trim();\n  if (!content) {\n    throw new Error('Failed to generate a cron expression');\n  }\n\n  return {\n    cronExpression: content,\n    _completion: response,\n  };\n}\n","import type { OpenAI } from 'openai';\n\nexport type HumanReadableToLookbackMinutesReturnType = {\n  minutes: number;\n  _raw?: string;\n};\n\nconst MINUTE = 1;\nconst HOUR = 60;\nconst DAY = 24 * HOUR;\n\nconst COMMON_MAP: Record<string, number> = {\n  '1h': HOUR,\n  '1 hour': HOUR,\n  'one hour': HOUR,\n  '2h': 2 * HOUR,\n  '2 hours': 2 * HOUR,\n  '6h': 6 * HOUR,\n  '6 hours': 6 * HOUR,\n  '12h': 12 * HOUR,\n  '12 hours': 12 * HOUR,\n  '24h': 24 * HOUR,\n  '24 hours': 24 * HOUR,\n  '1d': DAY,\n  '1 day': DAY,\n  day: DAY,\n  '30m': 30,\n  '30 minutes': 30,\n  '15m': 15,\n  '15 minutes': 15,\n};\n\n/**\n * Lightweight local parser for common patterns: \"X minutes/hours/days\"\n */\nexport function parseLookbackToMinutesLocal(text: string): number | null {\n  const t = text.toLowerCase().trim();\n  if (t in COMMON_MAP) return COMMON_MAP[t];\n\n  // e.g. \"last 6 hours\", \"6h\", \"6 hours\", \"90 minutes\", \"1 day\"\n  const re = /(last\\s+)?(\\d+(?:\\.\\d+)?)\\s*(minutes?|mins?|m|hours?|hrs?|h|days?|d)\\b/;\n  const m = t.match(re);\n  if (!m) return null;\n  const value = parseFloat(m[2]);\n  const unit = m[3];\n  if (Number.isNaN(value)) return null;\n\n  if (/^m(in(ute)?s?)?$/.test(unit)) return Math.round(value * MINUTE);\n  if (/^h((ou)?rs?)?$/.test(unit)) return Math.round(value * HOUR);\n  if (/^d(ays?)?$/.test(unit)) return Math.round(value * DAY);\n  return null;\n}\n\n/**\n * Uses OpenAI to convert a human prompt like \"last 6 hours\" into minutes\n */\nexport async function humanReadableToLookbackMinutes(\n  openai: OpenAI,\n  prompt: string,\n): Promise<HumanReadableToLookbackMinutesReturnType> {\n  const local = parseLookbackToMinutesLocal(prompt);\n  if (local !== null) {\n    return { minutes: local, _raw: 'local' };\n  }\n\n  const resp = await openai.chat.completions.create({\n    model: 'gpt-4o-mini',\n    temperature: 0,\n    messages: [\n      {\n        role: 'system',\n        content:\n          '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.',\n      },\n      { role: 'user', content: prompt },\n    ],\n  });\n  const content = resp.choices?.[0]?.message?.content?.trim();\n  if (!content) throw new Error('OpenAI returned empty content');\n  const minutes = parseInt(content.replace(/[^0-9]/g, ''), 10);\n  if (!Number.isFinite(minutes) || minutes <= 0) {\n    throw new Error('Failed to parse minutes');\n  }\n  return { minutes, _raw: content };\n}\n"],"names":[],"mappings":"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"}